下面是两种常见的分布式锁类型以及它们的底层原理和示例代码:
- 基于数据库的分布式锁:
基于数据库的分布式锁通过数据库的事务机制来实现锁机制。它的基本思想是通过在数据库中插入一条唯一的记录作为锁,其他节点在获取锁时会尝试插入相同的记录,如果插入成功,则表示获取到了锁。
public class DatabaseLock { private DataSource dataSource; public boolean tryLock(String lockKey) { try (Connection connection = dataSource.getConnection()) { connection.setAutoCommit(false); PreparedStatement statement = connection.prepareStatement("INSERT INTO locks(lock_key) VALUES(?)"); statement.setString(1, lockKey); try { statement.executeUpdate(); connection.commit(); return true; } catch (SQLException e) { connection.rollback(); return false; } } catch (SQLException e) { return false; } } public void unlock(String lockKey) { try (Connection connection = dataSource.getConnection()) { connection.setAutoCommit(false); PreparedStatement statement = connection.prepareStatement("DELETE FROM locks WHERE lock_key = ?"); statement.setString(1, lockKey); try { statement.executeUpdate(); connection.commit(); } catch (SQLException e) { connection.rollback(); } } catch (SQLException e) { // 处理异常 } } }
- 基于ZooKeeper的分布式锁:
基于ZooKeeper的分布式锁利用ZooKeeper的有序节点和监听机制来实现锁机制。每个节点在获取锁时会创建一个有序的临时节点,根据节点的顺序判断是否获取到了锁。如果节点的顺序最小,则表示获取到了锁。
public class ZooKeeperLock { private ZooKeeper zooKeeper; private String lockPath; private String currentPath; public boolean tryLock() { try { currentPath = zooKeeper.create(lockPath + "/lock_", null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL); List<String> children = zooKeeper.getChildren(lockPath, false); Collections.sort(children); String smallestPath = children.get(0); if (currentPath.equals(lockPath + "/" + smallestPath)) { return true; } CountDownLatch latch = new CountDownLatch(1); String previousPath = children.get(Collections.binarySearch(children, currentPath.substring(lockPath.length() + 1)) - 1); zooKeeper.exists(lockPath + "/" + previousPath, new Watcher() { @Override public void process(WatchedEvent event) { if (event.getType() == Event.EventType.NodeDeleted) { latch.countDown(); } } }); latch.await(); return true; } catch (Exception e) { return false; } } public void unlock() { try { zooKeeper.delete(currentPath, -1); } catch (Exception e) { // 处理异常 } } }
这两种分布式锁类型都有各自的优劣和适用场景。基于数据库的分布式锁简单易实现,但在高并发场景下性能可能不如基于ZooKeeper的分布式锁;而基于ZooKeeper的分布式锁具有高性能和强一致性的特点,但对ZooKeeper的依赖性较高。
总结起来,分布式锁是用于在分布式系统中实现互斥访问共享资源的一种锁机制。不同的分布式锁类型有不同的底层原理,可以根据实际需求选择合适的分布式锁实现。