ZooKeeper 有四种节点类型:
- 持久节点;
- 持久顺序节点;
- 临时节点;
- 临时顺序节。
利用 ZooKeeper 支持临时顺序节点的特性,可以实现分布式锁。
当客户端对某个方法加锁时,在 ZooKeeper 中该方法对应的指定节点目录下,生成一个唯一的临时有序节点。
判断是否获取锁,只需要判断持有的节点是否是有序节点中序号最小的一个,当释放锁的时候,将这个临时节点删除即可,这种方式可以避免服务宕机导致的锁无法释放而产生的死锁问题。
ZooKeeper 分布式锁流程:
- 客户端连接 ZooKeeper,并在根节点 /lock 下创建临时有序子节点,第一个客户端对应的子节点为 /lock/lock01/00000001,第二个为 /lock/lock01/00000002;
- 其他客户端获取 /lock01 下的子节点列表,判断自己创建的子节点是否为当前列表中序号最小的子节点;
- 如果是则认为获得锁,执行业务代码,否则通过 watch 事件监听 /lock01 的子节点变更消息,获得变更通知后重复此步骤直至获得锁;
- 完成业务流程后,删除对应的子节点,释放分布式锁。
在实际开发中,可以应用 Apache Curator 来快速实现分布式锁,Curator 对 ZooKeeper 原生 API 做了抽象和封装。