基于Zookeeper的分布式锁

13 5月

ZooKeeper是Apache软件基金会的一个软件项目,它为大型分布式计算提供开源的分布式配置服务、同步服务和命名注册。 ZooKeeper曾经是Hadoop的一个子项目,但现在是一个独立的顶级项目。

在Zookeeper中,znode是一个跟Unix文件系统路径相似的节点,可以往这个节点存储或获取数据。节点的类型又分为临时节点和永久节点,又可以带有序号。锁的本质是资源的占有,那么就需要有一个对象,在ZooKeeper中就可以是它的znode。所以最直接的锁思路就是占有一个znode。步骤如下:

  1. lock方法调用时尝试创建一个临时节点
  2. 如果节点创建成功,那么即获得锁
  3. 创建节点失败的就需要等待(等待可以是固定等待时间或者是使用Watch机制)
  4. 获得锁的线程释放锁时断开和ZooKeeper的链接即可

这个方法的问题在于等待,如果采用Watch机制,那么就容易出现大量订阅。

更常见的一种方法是将操作集中在一个目录中,比如/locker/user/。

在该目录下创建临时有序节点,那么没有获得锁的线程其实是可以感知其他线程的,比如最小序列是000001,而当前线程的序号是000010。大致方法如下:

  1. lock方法调用时创建临时有序节点
  2. 判断当前目录下的最小节点是否是自己持有的,如果持有就获得锁
  3. 如果最小节点不是自己获得的,那么就需要等待,可以watch最小节点的删除事件,而不是目录的情况
  4. 释放锁时断开链接即可

当然原理比较容易理解,但是实际使用中可以直接用封装好的,比如curator-recipes中的InterProcessMutex,InterProcessReadWriteLock等。

参考资料:

https://zookeeper.apache.org/doc/r3.1.2/recipes.html

https://www.jianshu.com/p/5d12a01018e1

 

 

发表评论

电子邮件地址不会被公开。