MySQL分布式鎖是一種用于在分布式系統(tǒng)間協(xié)調(diào)訪問共享資源的技術(shù)。在多個系統(tǒng)中同時訪問一個資源時,容易出現(xiàn)"腦裂"現(xiàn)象,進而導(dǎo)致數(shù)據(jù)一致性問題。因此,使用MySQL分布式鎖可以有效地避免這種問題的出現(xiàn)。
下面是MySQL分布式鎖的使用示例:
CREATE TABLE `distributed_lock` ( `lock_id` varchar(64) NOT NULL COMMENT '鎖ID', `lock_holder` varchar(64) NOT NULL COMMENT '持有者', `lock_time` bigint(20) NOT NULL COMMENT '加鎖時間', PRIMARY KEY (`lock_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; /** * 獲取分布式鎖 * * @param lockId 鎖ID * @param lockHolder 鎖持有者 * @param lockTimeout 鎖的過期時間 * @return true獲取成功,false獲取失敗 */ public boolean tryGetDistributedLock(String lockId, String lockHolder, long lockTimeout) { long now = System.currentTimeMillis(); try (Connection conn = dataSource.getConnection(); PreparedStatement ps = conn.prepareStatement( "INSERT INTO distributed_lock (lock_id, lock_holder, lock_time) " + "VALUES (?, ?, ?) " + "ON DUPLICATE KEY UPDATE lock_id = lock_id")) { while (true) { // 設(shè)置鎖的過期時間 long lockExpireTime = now + lockTimeout + 1; ps.setString(1, lockId); ps.setString(2, lockHolder); ps.setLong(3, lockExpireTime); // 嘗試獲取鎖 int affectedRows = ps.executeUpdate(); if (affectedRows == 1) { return true; } // 檢查鎖是否過期,如果過期則修改鎖的持有者 try (PreparedStatement selectStmt = conn.prepareStatement( "SELECT lock_time FROM distributed_lock WHERE lock_id = ?")) { selectStmt.setString(1, lockId); try (ResultSet rs = selectStmt.executeQuery()) { if (rs.next()) { long lockTime = rs.getLong(1); if (lockTime< now) { try (PreparedStatement updateStmt = conn.prepareStatement( "UPDATE distributed_lock SET lock_holder = ?, lock_time = ? WHERE lock_id = ?")) { updateStmt.setString(1, lockHolder); updateStmt.setLong(2, lockExpireTime); updateStmt.setString(3, lockId); affectedRows = updateStmt.executeUpdate(); if (affectedRows == 1) { return true; } } } } } } // 等待一段時間后再嘗試獲取鎖 Thread.sleep(10 + (int)(Math.random() * 100)); } } catch (Exception e) { e.printStackTrace(); return false; } } /** * 釋放分布式鎖 * * @param lockId 鎖ID * @param lockHolder 鎖持有者 * @return true釋放成功,false釋放失敗 */ public boolean releaseDistributedLock(String lockId, String lockHolder) { try (Connection conn = dataSource.getConnection(); PreparedStatement ps = conn.prepareStatement( "DELETE FROM distributed_lock WHERE lock_id = ? AND lock_holder = ?")) { ps.setString(1, lockId); ps.setString(2, lockHolder); int affectedRows = ps.executeUpdate(); return (affectedRows == 1); } catch (Exception e) { e.printStackTrace(); return false; } }