主要使用的zk的临时顺序节点概念,创建临时节点,并且是有序的,多线程在某个节点下创建同一个名称的节点,产生的有序节点。
什么是临时顺序节点,例如:
第一个客户端在produce目录下创建一个临时节点key为order,zk内部会给起个名字叫做:order-000001。
第二个客户端来也要创建一个临时节点在produce目录下,节点的key也是order,zk会起个名字叫做:order-000002数字都是依次递增的,从1开始逐次递增。zk会维护这顺序
创建节点:获取锁的过程:
第一步:创建一个临时顺序节点
第二步:获取当前目录下的所有临时顺序节点(不考虑当前目录下存在多个不同的key)
第三步:获取排序第一的临时节点
第四步:比较当前线程创建的临时节点和排序第一的节点是否相等,若相等当前线程获取锁。
第五步:若不相等,当前线程监听自己前面的一个节点(比自己序号小1的节点)。
第六步:若线程A释放锁,删除当前临时节点(删除排序第一的节点)
第七步:线程B再回到第二步,试着去获取锁(排序第一个已经删除,剩下的就是排序第一的)
其实如果有客户端C、客户端D等N个客户端争抢一个zk分布式锁,原理都是类似的。
1,大家都是上来直接创建一个锁节点下的一个接一个的临时顺序节点
2,如果自己不是第一个节点,就对自己上一个节点加监听器
3,只要上一个节点释放锁,自己就排到前面去了,相当于是一个排队机制。
而且用临时顺序节点的另外一个用意就是,如果某个客户端创建临时顺序节点之后,不小心自己宕机了也没关系,zk感知到那个客户端宕机,会自动删除对应的临时顺序节点,相当于自动释放锁,或者是自动取消自己的排队。
最后,咱们来看下用Curator框架进行加锁和释放锁的一个过程:
其实用开源框架就是这点好,方便。这个Curator框架的zk分布式锁的加锁和释放锁的实现原理,其实就是上面我们说的那样子。
但是如果你要手动实现一套那个代码的话。还是有点麻烦的,要考虑到各种细节,异常处理等等。所以大家如果考虑用zk分布式锁,
来源:https://mp.weixin.qq.com/s/fqtS2tYPaK6cAsqtcdbM-Q
作者:一起写程序