基于Zookeeper实现分布式锁解锁过程

147 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第9天,点击查看活动详情

前文回顾

  • 上文我们学习了上锁的过程,那么自然的本文就是解锁的文章了。

释放过程

释放锁分为两种情况:正常释放+中途中断

正常释放

  • 当我们线程业务处理结束之后,最后业务会调用zookeeper删除对应的节点。

异常中断

  • 如果我们线程正在处理业务中突然zookeeper奔溃了。那么犹豫我们节点临时性,那么当服务重启之后节点就丢失了。这个时候就无法保证当前线程的唯一执行的特权了。

  • 由于Client2一直监听着Lock1的存在状态,当Lock1节点被删除,Client2会立刻收到通知。这时候Client2会再次查询ParentLock下面的所有节点,确认自己创建的节点Lock2是不是目前最小的节点。如果是最小,则Client2顺理成章获得了锁。

  • 同理,如果Client2也因为任务完成或者节点崩溃而删除了节点Lock2,那么Client3就会接到通知。

  • 解决不可重入:客户端加锁时将主机和线程信息写入锁中,下一次再来加锁时直接和序列最小的节点对比,如果相同,则加锁成功,锁重入。

  • 锁释放时机:由于我们创建的节点是顺序临时节点,当客户端获取锁成功之后突然session会话断开,ZK会自动删除这个临时节点。

  • 单点问题:ZK是集群部署的,主要一半以上的机器存活,就可以保证服务可用性。

解决

Zookeeper第三方客户端curator中已经实现了基于Zookeeper的分布式锁。利用curator加锁和解锁的代码如下:

对比

  • 综合下来我觉得还是zookeeper比较适合我们的业务场景,能够保证分布式特性也能避免CPU问题。但是在实现上redis锁貌似更加的简单。这里主要看项目场景吧。没必要为了分布式锁单独引入其中的模块。推荐redis或者zookeeper