前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >阿里Java二面:了解分布式锁?说说ZooKeeper分布式锁的实现原理

阿里Java二面:了解分布式锁?说说ZooKeeper分布式锁的实现原理

作者头像
用户5546570
发布2019-11-21 17:57:05
4460
发布2019-11-21 17:57:05
举报

大家好,我是小寒!今天给小伙伴讲讲ZooKeeper分布式锁的实现原理!有自己看法的也可以在评论区留言探讨,也可以转发关注下我以后会长期分享!

什么是Zookeeper?

Zookeeper 是一个开放源码的分布式应用程序协调服务,它包含一个简单的原语集,分布式应用程序可以基于它实现同步服务、配置维护和命名服务等等。

阿里Java二面:了解分布式锁?说说ZooKeeper分布式锁的实现原理

分布式锁 简介

在我们进行单机应用开发,涉及并发同步的时候,我们往往采用synchronized或者Lock的方式来解决多线程间的代码同步问题。但当我们的应用是分布式集群工作的情况下,那么就需要一种更加高级的锁机制,来处理种跨机器的进程之间的数据同步问题。这就是分布式锁。

公平锁和可重入锁模型

分布式锁的概念和原理,比较抽象难懂。如果用一个简单的故事来类比,估计就简单多了。

很久以前,在一个村子有一口井,水质非常的好,村民们都抢着取井里的水。井就那么一口,村里的人很多,村民为争抢取水打架斗殴,甚至头破血流。问题总是要解决,于是村长绞尽脑汁,最终想出了一个凭号取水的方案。井边安排一个看井人,维护取水的秩序。说起来,秩序很简单,取水之前,先取号。号排在前面的,就可以先取水。先到的排在前面,那些后到的,没有排在最前面的人,一个一个挨着,在井边排成一队。取水示意图如下 :

阿里Java二面:了解分布式锁?说说ZooKeeper分布式锁的实现原理

这种排队取水模型,就是一种锁的模型。排在最前面的号,拥有取水权,就是一种典型的独占锁。另外,先到先得,号排在前面的人先取到水,取水之后就轮到下一个号取水,至少,看起来挺公平的,说明它是一种公平锁。

在公平独占锁的基础上,再进一步,看看可重入锁的模型。

假定,取水时以家庭为单位,哪个家庭任何人拿到号,就可以排号取水,而且如果一个家庭有一个人拿到号,其它家人这时候过来打水不用再取号。

新的排号取水示意图如下 :

阿里Java二面:了解分布式锁?说说ZooKeeper分布式锁的实现原理

如上图的1号,老公有号,他的老婆来了,直接排第一个,妻凭夫贵。再看上图的2号,父亲正在打水,他的儿子和女儿也到井边了,直接排第二个,这个叫做子凭父贵。 等等,如果是同一个家庭,可以直接复用排号,不用重新取号从后面排起。

以上这个故事模型,就是可以重入锁的模型。只要满足条件,同一个排号,可以用来多次取水。在锁的模型中,相当于一把锁,可以被多次锁定,这就叫做可重入锁。

zookeeper分布式锁的原理

理解了锁的原理后,就会发现,Zookeeper 天生就是一副分布式锁的胚子。

如果大家对zk还不太了解,建议先百度一下,快速了解一些基本概念,比如zk有哪些节点类型等等。

阿里Java二面:了解分布式锁?说说ZooKeeper分布式锁的实现原理

首先,Zookeeper的每一个节点,都是一个天然的顺序发号器。

在每一个节点下面创建子节点时,只要选择的创建类型是有序(EPHEMERAL_SEQUENTIAL 临时有序或者PERSISTENT_SEQUENTIAL 永久有序)类型,那么,新的子节点后面,会加上一个次序编号。这个次序编号,是上一个生成的次序编号加一

比如,创建一个用于发号的节点“/test/lock”,然后以他为父亲节点,可以在这个父节点下面创建相同前缀的子节点,假定相同的前缀为“/test/lock/seq-”,在创建子节点时,同时指明是有序类型。如果是第一个创建的子节点,那么生成的子节点为/test/lock/seq-0000000000,下一个节点则为/test/lock/seq-0000000001,依次类推,等等。

阿里Java二面:了解分布式锁?说说ZooKeeper分布式锁的实现原理

其次,Zookeeper节点的递增性,可以规定节点编号最小的那个获得锁。

一个zookeeper分布式锁,首先需要创建一个父节点,尽量是持久节点(PERSISTENT类型),然后每个要获得锁的线程都会在这个节点下创建个临时顺序节点,由于序号的递增性,可以规定排号最小的那个获得锁。所以,每个线程在尝试占用锁之前,首先判断自己是排号是不是当前最小,如果是,则获取锁。

第三,Zookeeper的节点监听机制,可以保障占有锁的方式有序而且高效。

每个线程抢占锁之前,先抢号创建自己的ZNode。同样,释放锁的时候,就需要删除抢号的Znode。抢号成功后,如果不是排号最小的节点,就处于等待通知的状态。等谁的通知呢?不需要其他人,只需要等前一个Znode 的通知就可以了。当前一个Znode 删除的时候,就是轮到了自己占有锁的时候。第一个通知第二个、第二个通知第三个,击鼓传花似的依次向后。

Zookeeper的节点监听机制,可以说能够非常完美的,实现这种击鼓传花似的信息传递。具体的方法是,每一个等通知的Znode节点,只需要监听linsten或者 watch 监视排号在自己前面那个,而且紧挨在自己前面的那个节点。 只要上一个节点被删除了,就进行再一次判断,看看自己是不是序号最小的那个节点,如果是,则获得锁。

基于zookeeper分布式锁的教学

zookeeper 可以根据有序节点+watch实现,实现思路,如:

为每个线程生成一个有序的临时节点,为确保有序性,在排序一次全部节点,获取全部节点,每个线程判断自己是否最小,如果是的话,获得锁,执行操作,操作完删除自身节点。如果不是第一个的节点则监听它的前一个节点,当它的前一个节点被删除时,则它会获得锁,以此类推。

为了方便阅读,对实现的代码这一块我就不展示了,在这提供学习视频免费分享给大家,有需要的朋友可以在这免费领取

视频教学的内容包括:

  1. 锁的本质
  2. CountDownLatch
  3. 分布式锁方案大全
  4. 模仿方法设计模式
  5. 数据库实现分布式锁方式
  6. Zookeeper学习
  7. 观察者设计模式
  8. 基于同名节点的分布式锁
  9. 高性能分布式锁

阿里Java二面:了解分布式锁?说说ZooKeeper分布式锁的实现原理

image.png

同时还免费分享更多Java架构进阶学习视频及学习文档资料,希望对您有所帮助!

有需要的朋友可以在这免费领取

阿里Java二面:了解分布式锁?说说ZooKeeper分布式锁的实现原理

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是Zookeeper?
  • 分布式锁 简介
  • zookeeper分布式锁的原理
  • 基于zookeeper分布式锁的教学
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档