如何使用zookeepe实现分布式锁--抄自小灰

在这里插入图片描述
1、zookeeper的四种节点类型:
a、持久节点:默认的节点类型,创建节点的客户端和zookeeper断开连接后,该节点依旧存在。

b、持久节点顺序节点:
在创建节点时,zookeeper根据创建的时间顺序给节点名称进行编号。如下所示:
在这里插入图片描述
c、临时节点
和持久节点相反,当创建节点的客户端与zookeeper断开连接后,临时节点会被删除。

d、临时顺序节点
临时顺序节点,结合了临时节点和顺序节点的特点:在创建节点时,zookeeper根据创建的时间顺序和该节点名称进行编号。当创建节点的客户端与zookeeper断开连接后,临时节点会被删除。

2、zookeeper分布式锁的原理
zookeeper分布式锁恰恰应用了临时顺序节点。如何实现呢?
a、获取锁
首先,在Zookeeper当中创建一个持久节点ParentLock,当第一个客户端想要获得锁时,需要在ParentLock这个节点下面创建一个临时顺序节点lock1。
在这里插入图片描述
之后,client1查找ParentLock下面所有的临时顺序节点并排序,判断自己所创建的节点lock1是不是顺序最靠前的一个,如果是第一个节点,则成功获得锁。
在这里插入图片描述
此时,如果有一个客户端client2前来获取锁,则在parentlock下再创建一个临时顺序节点lock2
在这里插入图片描述
client2查找parentlock下面所有的临时顺序节点并排序,判断自己所创建的节点lock2是不是顺序最靠前的一个,结果发现节点lock2并不是最小的。于是client2向排序仅比它靠前的节点lock1注册watcher,用于监听lock1节点是否存在。此时意味着client2抢锁失败,进入了等待状态。
在这里插入图片描述
此时,如果又有一个客户端client3前来获取锁,则在parentLock下再创建一个临时顺序节点lock3.
在这里插入图片描述
Client3查找parentLock下面所有的临时顺序节点并排序,判断自己所创建的节点lock3是不是顺序最靠前的一个,结果同样发现节点lock3并不是最小的。于是client3向排序仅比它靠前的节点lock2注册watcher,用于监听lock2节点是否存在。这同样意味着client3同样抢锁失败。并进入等待状态。
在这里插入图片描述
这就很有意思了,首次抢到锁的客户端获取到锁以后,由于每次来的客户端都会进行排序,也就是每个客户端都会生成一个watch来监听前一个是否释放了锁。(但是如果我希望每个客户端都需要有一个获取锁的超时时间呢?由于是临时节点,可以认为会自动释放,那是否也就意味着zookeeper中需要有一个自动更新watch的功能?)

b、释放锁
释放锁分为两种情况。
第一种情况:任务完成,客户端显示释放锁
当任务完成后,client1会显示调用删除节点Lock1的指令。而这个节点被删除后,会被watch监听到,然后后面的客户端就可以去获取到锁了。
在这里插入图片描述

第二种情况:任务执行过程中,客户端崩溃
获得锁的client在任务执行过程中,如果崩溃调了,就会断开与zookeeper服务端的链接。根据临时节点的特性,相关联的节点lock1会随之自动删除。
在这里插入图片描述
由于client2一直监听着lock1的存在状态,当Lock1节点被删除,client2会立刻收到通知,这时候client2会再次查询ParentLock下面的所有节点,确认自己创建的节点lock2是不是目前最小的节点,如果是最小,那么就获取到锁。

3、redis分布式锁和zookeeper分布式锁的优缺点比较:
在这里插入图片描述
实际工作中,我选择使用的是redis来实现分布式锁,之所以不使用zookeeper主要是由于需要引入这个zk框架,依赖相对而言变多了,而redis是当前我们就使用的工具,所以选用了redis。不过大家具体选择的时候还是要根据实际情况来分析。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章