实现分布式锁目前有三种流行方案,分别为基于数据库、Redis、Zookeeper 的方案,我们来看下使用 Zookeeper 如何实现分布式锁。
在 ZooKeeper 中,可以通过在 ZooKeeper 中创建一个数据节点来表示一个锁。比如,/exclusive_lock/lock 节点就可以表示为一个锁。
在需要获取排他锁时,所有的客户端都会试图通过 create() 接口,在 /exclusive_lock 节点下创建临时的子节点 /exclusive_lock/lock,但 ZooKeeper 的强一致性最终只会保证仅有一个客户单能创建成功,那么就认为该客户端获取了锁。同时,所有没有获取锁的客户端事务只能处于等待状态,这些处于等待状态的客户端事先可以在 /exclusive_lock 节点上注册一个子节点变更的 Watcher 监听,以便实时监听到子节点的变更情况。
我们已经提到 /exclusive_lock/lock 是一个临时节点,因此在以下两种情况下可能释放锁。
- 当前获取锁的客户端发生宕机,那么 ZooKeeper 服务器上保存的临时性节点就会被删除;
- 正常执行完业务逻辑后,由客户端主动来将自己创建的临时节点删除。
无论什么情况下,临时节点 /exclusive_lock/lock 被移除,ZooKeeper 都会通知在 /exclusive_lock 注册了子节点变更 Watcher 监听的客户端。这些客户端在接收到通知以后就会再次发起获取锁的操作,即重复“获取锁”过程。排他锁流程如下:
假如当前有 100