范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

22张图带你彻底弄懂Zookeeper分布式锁

  这篇文章就来剖析Zookeeper分布式锁的实现框架Curator的源码,看看Curator是如何实现Zookeeper分布式锁的,以及它提供的哪些其它的特性。
  Curator框架是封装对于zk操作的api,其中就包括了对分布式锁的实现,当然Curator框架也包括其它的功能,分布式锁只是Curator的一部分功能。 一、ZK分布式锁实现原理
  实现Zookeeper分布式锁,主要是基于Zookeeper的临时顺序节点来实现的。
  当客户端来加锁的时候,会先在加锁的节点下建立一个子节点,这个节点就有一个序号,类似 lock-000001 ,创建成功之后会返回给客户端所创建的节点,然后客户端会去获取这个加锁节点下的所有客户端创建的子节点,当然也包括自己创建的子节点。拿到所有节点之后,给这些节点进行排序,然后判断自己创建的节点在这些节点中是否排在第一位,如果是的话,那么就代表当前客户端就算加锁成功了,如果不是的话,那么就代表当前客户端加锁失败。
  加锁失败的节点并不会不停地循环去尝试加锁,而是在自己创建节点的前一个节点上加一个监听器,然后就进行等待。当前面一个节点释放了锁,就会反过来通知等待的客户端,然后客户端就加锁成功了。
  为什么需要在前一个节点加个监听器?
  假设有很多客户端来加锁,然后加锁失败的都对前一个节点加一个监听。那么一旦第一个加锁成功的客户端线程释放了锁,那么被唤醒的就是第二个客户端线程,第二个客户端线程就会加锁成功,执行完任务之后就释放了锁,那么就会唤醒第三个客户端线程,第三个客户端线程加锁成功,执行完任务之后就释放了锁,唤醒第四个客户端线程,以此类推,所以每次释放锁都会唤醒下一个节点,这样每个加锁的线程都会加锁成功,所以监听器的作用是唤醒加锁失败阻塞等待的客户端。 二、为什么使用临时顺序节点
  下面介绍一下临时节点、持久化节点、顺序节点的特性。
  1)临时节点
  临时节点,指的是节点创建后,如果创建节点的客户端和 Zookeeper 服务端的会话失效(例如断开连接),那么节点就会被删除。
  2)持久化节点
  持久化节点指的是节点创建后,即使创建节点的客户端和 Zookeeper 服务端的会话失效(例如断开连接),节点也不会被删除,只有客户端主动发起删除节点的请求,节点才会被删除。
  3)有序节点
  有序节点,这种节点在创建时会有一个序号,这个序号是自增的。有序节点既可以是有序临时节点,也可以是有序持久化节点。
  从上面节点的特性可以知道,临时节点相比持久节点,最主要的是对会话失效的情况处理不一样,如果使用临时节点的话,如果客户端发生异常的话,没有来得及主动释放锁,就能避免锁无法释放导致死锁的情况。因为一旦客户端异常,那么客户端和服务端之间的会话就会失效,然后临时节点就会被删除,这样就释放了锁;而持久化节点在由于会话失效无法被删除,那么就不会去释放锁,这样就会产生死锁的问题。
  从这里可以看出redis和zk防止死锁的实现是不同的,redis是通过过期时间来防止死锁,而zk是通过临时节点来防止死锁的。
  为什么使用顺序节点?其实为了防止羊群效应。如果没有使用顺序节点,假设很多客户端都会去加锁,那么加锁就会都失败,都会对加锁的节点加个监听器,那么一旦锁释放,那么所有的加锁客户端都会被唤醒来加锁,那么一瞬间就会造成很多加锁的请求,增加服务端的压力。
  所以综上,临时顺序节点是个比较好的选择。 三、加锁的逻辑是如何实现的
  前面关于ZK分布式锁实现原理已经说过了,接下来就来看一下代码的实现。
  加锁的使用方法如下,接下来几节会着重讲解这段代码背后的逻辑
  acquire方法的实现
  acquire方法会去调用internalLock方法,传入超时时间 -1 和单位 null,也就代表了如果加锁不成功会一直阻塞直至加锁成功,不会超时。
  internalLock方法会先去获取当前线程,然后从threadData中获取当前线程对应的LockData,这里面封装了加锁的信息和次数,是实现可重入锁的关键,当然第一次加锁这里肯定是没有的,会继续下走 internals.attemptLock 加锁。
  attemptLock方法
  先通过driver的createsTheLock去创建节点。
  从这里看出,创建的节点类型是临时顺序节点,创建成功之后,就会返回当前创建的节点。
  节点创建成功之后,会调用internalLockLoop方法来加锁。
  通过getSortedChildren方法获取排好序的子节点,然后获取当前的节点名称,再通过 driver.getsTheLock判断当前的节点有没有加锁成功,返回一个PredicateResults判断的结果,这里面存的就是否加锁成功的信息。
  第一次加锁,那么到这里就加锁成功了。之后就会封装一个LockData对象,放入threadData 的map中。
  加锁的流程如下图:
  四、如何实现可重入加锁
  上文加锁的时候提到了,当第一次加锁成功之后,会往threadData放入该加锁的线程对应的LockData。
  LockData主要封装了当前线程、加锁的次数、加锁的节点。
  此时如果第二次来加锁,那么就会从threadData中获取到加锁的信息,然后将加锁次数加1,就代表了加锁成功,然后直接返回。
  所以可重入加锁的实现很简单,就是在客户端中判断有没有加过锁,加过的话就将加锁次数累加1,压根就跟服务端没有交互。
  注意Redisson可重入加锁的实现跟的Curator是不一样的,Redisson的加锁次数是存在Redis的服务端的,而Curator是存在客户端的。
  五、加锁失败之后如何实现阻塞等待加锁
  前面加锁的逻辑主要是说了加锁成功的情况,这里就来说一下加锁失败的情况。
  继续来看internalLockLoop方法。
  前面说过,判断有没有加锁成功,会返回一个PredicateResults,这里面包含了有没有加锁成功的信息,同时如果没有加锁成功,就会返回需要监听的节点,也就是当前创建的节点的前一个节点。
  所以没有加锁成功,就会走else的逻辑,对上一个节点加一个监听器 watcher
  然后就会调用 wait 方法,进行等待。
  当前一个节点被删除了,也就是释放了锁,那么就会回调这个监听器watcher的方法。
  所以,这个watcher的作用就是调用notifyAll方法唤醒调用wait方法的线程,这样线程就会继续尝试加锁,因为是在一个while的循环中。 六、如何实现阻塞等待一定时间还未加锁成功就放弃加锁
  可通过下面这个方法来实现实现阻塞等待一定时间还未加锁成功就放弃加锁。 boolean acquire(long time, TimeUnit unit) throws Exception 复制代码
  这个方法相比不指定等待时间的方法最主要的区别就是加锁失败之后,调用的阻塞的方法不一样。当不指定超时时间就会调用wait()方法,不会传入等待时间,不被唤醒就会一直阻塞;指定超时时间的时候,就会调用wait(long timeout)指定等待的时间,这样如果等待时间一到,线程就会醒过来,然后再次尝试加锁,一旦加锁失败,就会放弃加锁。
  七、如何主动释放锁和避免其它线程释放锁
  释放锁release方法
  释放锁其实很简单,就是拿出当前线程对应的LockData,如果没有,就说明当前线程没有加过锁,就会抛出异常,所以Curator就是通过这个判断来防止其它线程释放了自己线程加的锁。
  如果加锁了,那么LockData就不会为null,然后将加锁次数递减1,得到newLockCount,代表了剩下的加锁次数。如果newLockCount > 0,说明锁没释放完,有可重入加锁,然后什么事都不干,直接返回了。如果newLockCount < 0,就抛异常,但是一般不会出现。剩下的一种情况就是newLockCount == 0 ,说明锁已经完完全全释放完了,然后通过internals.releaseLock删除加锁的节点。
  服务端删除节点之后,就会通知监听该节点的客户端,然后客户端就会回调watcher监听器,唤醒阻塞等待的线程,线程被唤醒后再进行一次判断就能加锁成功。
  到这里,就讲完了加锁和释放锁的过程,整个加锁和释放锁的过程就如下图所示。
  八、如何实现公平锁
  其实使用临时顺序节点实现的分布式锁就是公平锁。所谓的公平锁就是加锁的顺序跟成功加锁的顺序是一样的。
  因为节点的顺序就是被唤醒的顺序,所以也就是加锁的顺序,所以天生就是公平锁。九、如何实现读写锁
  读写锁使用如下。
  创建节点的时候,节点的内容中会有一个标记来代表当前节点加的是什么类型的锁。
  当需要加写锁时,需要判断自己创建的节点是否排在第一位,如果是就能加锁成功,所以一旦前面有节点,不论前面加是读锁还是写锁,那么都是加锁失败,实现了读写互斥和写写互斥。当然写锁和读锁都是可以重入加锁的。
  当需要加读锁的时候,会去判断自己创建节点的前面有没有写锁,如果没写锁,那么说明前面加的都是读锁,那么读锁就能加锁成功,读读不互斥,如果前面有写锁,那么就加锁失败(自己加的写锁除外),读写互斥。十、如何实现批量加锁
  批量加锁的意思就是同时加几个锁,只有这些锁都算加成功了,才是真正的加锁成功。
  Redisson也实现了批量加锁的功能,Redisson的实现通过RedissonMultiLock类实现的,RedissonMultiLock会去遍历需要加的锁,然后每个都加成功之后才算加锁成功。Curator是封装了InterProcessMultiLock类来实现的批量加锁的,那么InterProcessMultiLock如何实现的呢?
  使用代码如下。
  InterProcessMultiLock的acquire的方法实现。
  从这里可以看出,InterProcessMultiLock也是遍历传入的锁,然后每个锁都加锁成功了,InterProcessMultiLock才算加锁成功。
  所以从这里可以看出,跟Redisson实现的批量加锁的实现思想上基本是一样的,都是遍历加锁。十一、ZK分布式锁和Redis分布式锁到底该选谁
  这是一个比较常见的面试题。
  redis分布式锁:优点:性能高,能保证AP,保证其高可用,缺点:正如Redisson的那篇文章所言,主要是如果出现主节点宕机,从节点还未来得及同步主节点的加锁信息,可能会导致重复加锁。虽然Redis官网提供了RedLock算法来解决这个问题,Redisson也实现了,但是RedLock算法其实本身是有一定的争议的,有大佬质疑该算法的可靠性;同时因为需要的机器过多,也会浪费资源,所以RedLock也不推荐使用。
  zk分布式锁:优点:zk本身其实就是CP的,能够保证加锁数据的一致性。每个节点的创建都会同时写入leader和follwer节点,半数以上写入成功才返回,如果leader节点挂了之后选举的流程会优先选举zxid(事务Id)最大的节点,就是选数据最全的,又因为半数写入的机制这样就不会导致丢数据缺点:性能没有redis高
  所以通过上面的对比可以看出,redis分布式锁和zk分布式锁的侧重点是不同的,这是redis和zk本身的定位决定的,redis分布式锁侧重高性能,zk分布式锁侧重高可靠性。所以一般项目中redis分布式锁和zk分布式锁的选择,是基于业务来决定的。如果你的业务需要保证加锁的可靠性,不能出错,那么zk分布式锁就比较符合你的要求;如果你的业务对于加锁的可靠性没有那么高的要求,那么redis分布式锁是个不错的选择。

炎亚纶被汪东城破大防了,直戳他的玻璃心,反手拉黑了网友近日,炎亚纶因为台独言论以及对一个中国的原则的态度,先是阴阳怪气INS图文内涵,退出因粉丝修改群名的群(只有一个中国),再是自我解约在中国自创的品牌。这几天一顿猛操作,让多年追随他52岁的王璐瑶,被网友推荐接替于月仙演谢大脚,如今发福烟不离手最近,一代女神王璐瑶的近照曝光,引发了不少人的关注。王璐瑶曾经是娱乐圈炙手可热的女演员,出演过雪山飞狐里的苗若兰,这个角色到现在还是不少人心目中的经典形象。如今王璐瑶已经五十二岁,从8月2日佩洛西访台到今日被大V和网友忽略的细节忽略细节一几个小时的静默8月2日无数网友的目光全盯在了佩洛西的专机上,世界的焦点也汇集于此,而我于8月2日19点打开电视,(我相信很多网友N长时间没看过电视了,甚至好多都不知电视打那些情侣同居之后才知道的小秘密,情侣们应该了解刚开始恋爱的时候都会陷入甜蜜之中,生活中一些热恋期的男女,,就是每天在想方设法的,无时无刻都想待在一起,没有机会也要制造机会!很多人在这个阶段,是被爱情冲昏了头脑,就算是对方的一些A股国内网络安全板块的TOP,仅有五家,谁会率先崛起?国内网络安全板块的TOP,仅有五家,谁会率先崛起?没有网络安全就没有国家安全。安全是发展的前提,发展是安全的保障。据报道,当前以互联网大数据云计算人工智能为标志的新科技革命推动数字郭富城晒照为妻子庆生,戴情侣钻石手镯,盘子般大蛋糕被嘲太小气饿了吗?戳右边关注我们,每天给您送上最新出炉的娱乐硬核大餐!8月5日深夜,郭富城更新社交平台动态,晒出为妻子庆生的照片,并配文称祝亲爱的老婆生日快乐。照片中,方媛身穿玫红色短袖,下江苏学霸情侣相恋8年,本科相识,博士毕业结婚,还是校友!网友羡慕了人生漫漫,岁月匆匆。在精彩的青春校园里,遇到那个愿与之携手共度余生的人是一种幸运。有人说,爱情与学业无法兼得。南京信息工程大学的朱家杉和高思楠两人却做到了!他们从本科相遇到博士毕业海峡中线已不存在,军演继续延长10日!台湾省回归指日可待一军演持续进行这几日,我军对台联合军演已经圆满完成各项任务,把台湾省围得水泄不通。彻底打击了台独的嚣张气焰,也粉碎了美国霸权的一个重要棋子。此次军演可谓是中国下的一手好棋,当年我军华春莹犀利反问若有国家支持美国的一个州独立建国,你们愿意吗8月5日中国外交部召开例行记者招待会,有记者提问时表示,美国白宫国家安全委员会协调员约翰柯比公开指责中国单方面的行动加剧两岸局势紧张,要求中国立马收手。对此华春莹回应称,面对美方颠3比0北京,河南已是超强队!三只小老虎真生猛,红魔啦啦队最爱戴河南嵩山终于回到主场,万千红魔锣鼓喧天,气氛火爆异常,这就是河南足球氛围,也是河南人爱足球的炙热表现!没有给我们丝毫遗憾,摧枯拉朽的表现,把曾经豪门北京打得体无完肤!3比0,个个进A股大跌真凶是谁?刚刚1条消息引发热议,本周股市捍卫国家而战首先咱们现在看一下亚太市场,今天全部下跌,包括港股横生,日本方面,上证创纸,深成指全部下移,要捍卫自己的国家,这个时刻才是咱们真正要凸显自己价值观的时刻,在整个A股历史乃至中国历史
解析宁德时代CTP3。0麒麟电池技术什么是麒麟电池了解麒麟电池先要理解什么是CTP技术,CTP将电动车的电池与底盘做融合的技术,英文全称为celltopack,也就是无模组动力电池包,为什么要做无模组动力电池包呢?本骁龙888处理器为什么还有人用?看到小米11系列的做法我悟了一台手机的性能怎么样,除了厂商的调教,处理器肯定是至关重要的。前两年国内厂商真的是被三星的制程工艺给坑了,发布的骁龙888处理器直接成为了火龙,让众多厂商的口碑一落千丈。为了赶紧把外媒苹果危险了作为半导体行业的巨头,美国可以说得上在业界有着极高的话语权了,在前一个阶段,美国对华实行的实体清单制度当中,就对中国的半导体行业进行了很严重的一场打击。在这场角逐当中,华为一度被美肠道出现问题,身体会有这3个危险信号,要留意现如今,大家生活质量是越来越高了,吃的也是越来越好了,但是肠道问题却越来越严重了,这到底是什么情况呢?其实跟生活节奏加快有关,上班族总是朝九晚五,还有一部分工作多的时候需要熬夜,经联想小新Pro13,笔记本硬盘容量怎么办?手把手教你添加硬盘随着电子办公信息化进程的加快,很多人选择了使用笔记本办公。而笔记本一般标配的硬盘都在512GB。随着数据的增多,特别是微信数据急剧的膨胀,笔记本硬盘容量也捉襟见肘。很不幸,我也是其被asList坑了后,整理出Java数组与集合相互转换正确方式啤酒满怀忧思,不如先干再说!做干净纯粹的技术分享!欢迎评论区或私信交流!本文记录一下数组和集合相互转换的几种方法和一些坑,自己总结的同时也分享给有缘人,希望在工作和面试的时候有所帮一览最近完成融资的7个有趣的Web3项目原文作者Ann原文编译白泽研究院跟上加密行业潮流的一种方法是跟踪风险投资公司的动作。尽管处于熊市,但资本似乎并没有停止流向加密行业。与前一年相比,它的速度要慢得多,但无论如何,少数介绍一款基于系统思维原理打造的知识管理应用OneMind平行大脑OneMind平行大脑主界面OneMind作为一款升级版的超级脑图工具,可以用来实现个人知识体系的管理,不仅可以像常规脑图一样实现单个知识体系的管理,还可以建立不同知识体系之间的关2023开新局,五台云海二期项目跑出加速度2022年8月,五台云海二期10万吨高性能镁基轻合金及压延深加工项目在五台县东冶镇大朴村举办开工奠基仪式。这半年来,该项目的实施一直在有条不紊的进行。2023年2月21日,五台县委春游模式走起,邂逅第一抹春色!春回大地,草木萌发。气温回暖,市民纷纷来到户外踏青赏花。2月26日,白龟湖国家城市湿地公园一溪流景观旁,一簇簇迎春花儿绽放,吸引爱美市民驻足拍照白鹭洲国家城市湿地公园梅林,连片开放先进工艺需求下降,三星也降价抢28纳米,中国芯片的选择是对的三星是全球唯一可以与台积电竞争先进工艺的芯片制造企业,日前消息指三星意外地降低成熟工艺的代工价格,希望以价格优势抢夺成熟工艺市场,这一措施的目标似乎与中国大陆和台积电。三星已量产全