分布式锁实现方案

方案一

image.png

比如 ClientA、ClientB、ClientC 都在 Zookeeper 的 /locks 节点下创建子节点 /lock,按照 Zookeeper 本身的节点特性,在同一级节点里面,节点的名称必须是唯一的,所以只会有一个客户端成功创建 /lock 节点,其他客户端都失败,失败之后其他客户端都会监听 /locks 节点的变化,如果 /locks 的子节点发生变化了,会触发 Watcher 通知,这样其他客户端就会收到事件,再一次争抢锁。

这种实现方案存在一个问题,叫惊群效应,比如存在很多客户端都在监听 /locks 节点的子节点变化,一旦某个获得了锁的客户端释放了锁,会触发大量是 Watcher 事件,去通知其他客户端来争抢锁,而最终只会有一个客户端获得锁,当我们的客户端比较多的情况下,不建议使用这种方案。

方案二

image.png

ClientA、ClientB、ClientC 都在 Zookeeper 的 /locks 节点下创建一个有序子节点,而获得锁的操作是在所有节点中获取一个序号最小的节点,表示该节点对应的客户端获得了锁,其他节点会进入等待状态,并且其他的节点会向上监听,也就是说,/lock_seq2 节点会监听 /lock_seq1 节点,/lock_seq1 节点会监听 /lock_seq0 节点,当 /lock_seq0 节点释放了锁,/lock_seq1 节点会收到事件,会再次判断 /lock_seq1 节点是不是所有节点中序号最小的节点,如果是的话就表示获得锁。

对比方案二和方案一,方案二不会出现惊群效应,对 /lock_seq0 节点来说,只存在一个监听它的节点。

原生 API 实现分布式锁

Git 地址:https://gitee.com/yin_jw/demo/tree/master/zookeeper-demo

Curator API 实现分布式锁

Git 地址:https://gitee.com/yin_jw/demo/tree/master/zookeeper-demo

分析 Curator 实现分布式锁的原理

TODO:待优化