Zookeeper分布式锁的原理
Zookeeper 分布式锁就是利用顺序临时节点和Watch监听机制
初始化:
- 在 zk 中创建一个持久节点 ParentLock;
Client1 获取锁:
- 在 ParentLock 节点下创建临时顺序节点 Lock1;
- Client1 查找 ParentLock 下所有的临时顺序节点并排序;
- 判断自己所创建的节点是不是最靠前的一个,如果是则成功获取锁。
Client2 获取锁:
- 在 ParentLock 节点下创建临时顺序节点 Lock2;
- Client2 查找 ParentLock 下所有的临时顺序节点并排序;
- 判断自己所创建的节点是不是最靠前的一个,结果发现不是;
- Client2 向排序仅比它靠前的节点 Lock1 注册 Watcher,用于监听 Lock1 节点是否存在,这也就意味着抢锁失败,进入了等待状态。
Client3 获取锁:
- 在 ParentLock 节点下创建临时顺序节点 Lock3;
- Client3 查找 ParentLock 下所有的临时顺序节点并排序;
- 判断自己所创建的节点是不是最靠前的一个,结果发现不是;
- Client3 向排序仅比它靠前的节点 Lock2 注册 Watcher,用于监听 Lock2 节点是否存在,这也就意味着抢锁失败,进入了等待状态。
这样一来,Client1 得到了锁,Client2 监听了 Lock1,Client3 监听了 Lock2
Client1 释放锁:
- 显示调用删除 Lock1。
如果 Client1 没释放锁之前,崩溃了,怎么办?
- Client1 崩溃了则会断开与 Zookeeper 服务端的连接。根据临时节点的特性,相关联的节点 Lock1 会随之自动删除。
- 由于 Client2 一直监听着 Lock1 的存在状态,当 Lock1 节点被删除,Client2 会立刻收到通知,这时候 Client2 会再次查询 ParentLock 下面的所有节点,判断自己创建的节点 Lock2 是不是顺序最靠前的一个,如果是,则成功获取锁。
开源实现
Curator Recipes 模块已经有了完善的分布式锁实现。Curator Lock 相关的实现在 recipes.locks 包里,顶级接口都是 InterProcessLock。
Curator Recipes 锁的几种方案,InterProcessLock 接口实现类:
InterProcessMutex:分布式可重入排它锁
InterProcessSemaphoreMutex:分布式排它锁
InterProcessReadWriteLock:分布式读写锁
InterProcessMultiLock:将多个锁作为单个实体管理的容器