在上一篇文章中,我们介绍了怎么使用Redis实现分布式锁。没看的小伙伴可以点击下面链接: 前文阅读:《原来这就是分布式锁!这下懂了。。。1分钟系列》 今天我们就介绍如何用Zookeeper来实现分布式锁? 对Zookeeper不熟悉的同学,可以参考之前的文章: 《Zookeeper到底是个什么鬼?这下懂了。。。1分钟系列》 在此之前,我们首先要了解一下Zookeeper的临时顺序节点。 让我们回顾一下Zookeeper节点的概念,Zookeeper的数据存储结构就像一棵树,树的节点叫做Znode。 Znode分为四种类型: 1、持久节点 创建节点的客户端与zookeeper断开后,节点仍然存在。 2、持久节点顺序节点 所谓顺序,就是在创建节点时,Zookeeper根据创建的时间顺序给该节点名称进行编号。没办法,到哪都得排资论辈 3、临时节点 持久节点是有编制的合同工,临时节点就是跑龙套的群众演员。当创建节点的客户端与zookeeper断开后,临时节点就会被删除: 4、临时顺序节点 最悲催的存在,结合了临时节点和顺序节点的特点:创建节点时,Zookeeper根据创建的时间顺序给该节点名称进行编号;当创建节点的客户端与zookeeper断开后,临时节点就会被删除。 Zookeeper分布式锁恰恰利用了临时顺序节点。具体是怎么实现的呢?让我们来看一下: 获取锁 首先,在Zookeeper当中创建一个持久节点ParentLock。当第一个客户端想要获得锁时,需要在ParentLock这个节点下面创建一个临时顺序节点Lock1。 之后,Client1查找ParentLock下所有的临时顺序节点,并排序。判断自己创建的节点Lock1是不是最靠前的一个?如果是则成功获得锁。 这时,如果再有一个客户端Client2想要获取锁,则在ParentLock下再创建一个临时顺序节点Lock2。 Client2同样查找并判断自己所创建的节点Lock2是不是最靠前的一个?结果发现它前面有一个Lock1。 于是,Client2抢锁失败,进入等待状态。它向Lock1注册监听,等待前面的锁释放。 如果这时,又有一个客户端Client3前来获取锁,则会再创建一个临时顺序节点Lock3。 同样,Client3发现节点Lock3并不是最小的。于是,它向排在它前面Lock2注册监听,并进入等待状态。 这样一来,Client1得到了锁,Client2监听了Lock1,Client3监听了Lock2。这就形成了一个等待队列。 释放锁 释放锁分为两种情况: 1、客户端显示释放 当任务执行完毕后,Client1会调用删除节点Lock1的指令。 2、执行过程中,客户端崩溃 如果Client1在执行过程中,咣当崩溃了,则会断开与Zookeeper的连接。根据临时节点的特性,节点Lock1会随之被删除。 不管是哪种情况,Client2一直监听着Lock1,当Lock1节点被删除,Client2就会马上收到通知。这时,Client2就获得了锁。 同理,如果Client2执行完毕,或者中途崩溃了。那么节点Lock2就会被删除,Client3就会收到到通知,最终获得锁。 Apache的开源框架ApacheCurator,包含了对Zookeeper分布式锁的实现,有兴趣的小伙伴可以查看:https:github。comapachecurator 关注【老张聊架构】,成为百万年薪架构师!