Skip to main content

Command Palette

Search for a command to run...

关于分布式锁的总结

Updated
1 min read

1. 背景

最近做了一个分布式的调度系统,调度系统是分布式的,有一些任务我希望能做到单个节点去完成,所以就产生了主的概念;也就是多节点选择抢占出来一个节点,这个节点能唯一去做一些事情,当然也希望这个节点故障的时候能重新触发抢占并达到系统的容错性;

自己在设计的时候出现了一种混淆,节点本身的健康度和抢占两个逻辑的混淆,所以想通过这个文章来总结这方面的内容;并且后期会开源一个工具,能依赖各种后端存储来实现一套分布式锁的工具;

2. 分布式锁

对于分布式锁的关键点在于几点:

  • 如何实现抢占: 具体来将就是多方发起请求,能保证原子的抢占成功;也就是最终只会有一方能成功的抢占到;

    通常这种能力都是对应后端服务来提供的;比如:

    • Mongo:findAndModify接口,符合条件才能进行更新,并且可以设置如果不存在可以写入成功;
    • Redis: SETNX lockName true, 能原子的写入某一个key;
    • ZK: ephemeral node,可以原子的创建临时节点
    • ETCD: 提供类似于CAS的方式来进行更新;
  • 失效机制: 这个非常重要,如何保证当一个节点故障的时候,不会因为这个问题导致锁长期被占用;也是提供整个分布式锁的容错性;失效机制通用实现的方式是Lease,也就是每一个锁都有着占用时间长度,超过这个时间长度就会失效,这样能保证即使节点挂了,过了租期之后就会进行失效,可以保证其他的用户能占用这个锁;

    用什么方式去实现租期呢,有几种方式:

    • 基于mongo服务的类型的话,可以通过设置过期时间;其他的用户在抢占锁的时候通过对过期时间是否过期作为条件能抢占锁,如果锁本身已经过期那么抢占就会成功;
    • 基于redis是有一个命令SET lock_name value NX EX 10, 大概意思是设置一个锁,并且有效期为10秒
    • ZK: zk的临时节点貌似是基于session的,如果节点挂了session也就没了;
    • ETCD:可以直接设置key的过期时间;
  • 自动续租期: 主要是针对锁的时间长短的问题;比如一个操作可能需要很长的操作时间,并且也不确定要多久,这个时候就可以开启自动续约租期;这样只需要手动进行调用关闭即可;

    但是关于这个问题在于:自动续约的功能可能会导致一些其他的问题;比如当占用锁的用户可能因为操作过程因为hang住,并且自动续期又正常工作的话,那就会带来lock没办法被释放; 关于这点有点很难办,可能需要具体场景具体做分析优化吧;

    比如在mongo中就遇到过这样的问题,因为心跳链接是提前创建好的,mongo本身因为一些bug已经卡死了,但是心跳还是能正常工作,就导致不会进行主动的切主操作;所以所谓的健康度检测可能还是需要能正式反应业务是上是否正常来评估;

    关于这个租期的问题,其实也是我当时混淆进去的一点;我把节点的健康检测和租期续约给混在一起,导致写出来的代码有点混乱;目前我的思路可能是健康检测是健康检测;如果健康检测发现有问题的话,可以重启或者让自动续约的逻辑可以注入是否健康的函数,如果本节点已经不健康了就不进行续约之类的;

  • 锁过期之后的处理

    这个比较重要,假如一个程序以为自己占用了一个锁,但是本质上这个锁已经过期了需要如何处理;这其实并不好处理,原因是程序在执行过程中会有很多次停顿,不可能从所有停顿的地方都进行判断,比如java的gc的stop world,等程序从gc中回来的时候它可能根本不知道自己已经不占用锁,也会正常的做操作,这可能就是分布式带来的问题;如果是淡单机的lock就不会有这样的问题,因为单机本身lock是不会有所谓的过期,完全保证原子性,而分布式只能通过超时的方式来处理lock的有效性问题;

    我对这块的处理是这样的;

    1. 分布式锁后端会开启一个过期的探测,用户可以往里面注册回调,当lock过期的会触发回调,这样可以让用户去觉得如何才能中断你的处理逻辑;
    2. 上面的这种探测会因为锁是否开启自动续约会有不同的机制;
  • release lock

    这个主要问题在于unlock会不会释放别人的锁,这个比较尴尬;解决的方式还是在于lock是有ownership的,你unlock的时候需要对ownership进行验证,这样的话如果不是你的锁或者你的锁过期了的话,解锁过程也是对系统不会造成影响的;

3. 目前没有涉及的问题

网上有很多的问题其实并不是关于分布式锁如何实现,而且关于分布式锁依赖的后端如果没有高可用怎么办;最典型的就是redis了,不过这次我不讨论这个,等我研究一下中间可能存在的问题和解决思路再来写一篇总结;目前我选的是mongo,mongo支持多副本高可用强一致性的,所以用类似的就没这些问题;

More from this blog

Ai时代的工具链

本周是black Friday,我订阅了几个AI服务,还是蛮贵的...不过这样基本上构成我目前整体的知识阅读的过程,随着Ai的不断发展,工具链的替换可能是很重要的一个过程的。我主要订购了以下几个工具: Memo: 这个工具的主要作用是将视频/audio转srt,并且带有ai翻译的工具;当然我觉得它做的非常好的是,它把整个链路做的非常好的,并且可以用本地的资源做audio->text;而且它自带了很多的ai功能,比如对字幕进行进一步的AI的处理,提问,summarize和思维导图等等;目前我主要...

Nov 30, 20251 min read

做了一个噩梦

今天凌晨4点多起来看了一眼丈母娘的发烧是否ok...就导致我有点睡不着的,刷了一会推特之后又开始睡觉了,于是就开始做了一个很可怕的梦。 噩梦 那天,我不知道是在哪里..我带着女儿和我弟出去玩的,貌似是一个风景山区。于是我就带着女儿和弟弟出去玩的;我们走啊走, 沿着一条路一直走..突然看到一个小道有一家饭店的,这个饭店是比较特殊,有很多海鲜的;我看上了一只大龙虾,我问多少钱的,他说大概就70rmb就可以的。。。我觉得很划算的,我心想:我买下来,到时候把老婆叫过来一起吃的,并且告诉她这个才70rmb...

Nov 24, 20251 min read

子女教育-2

下面我分享一个推特上的一个关于子女教育的推 哈哈哈哈,李诞这个视频我看过 我给你分享几个我和我女儿之间的小故事 第一个故事 我经常给小朋友说:你们现在上学的成绩不重要,你们现在数学考试都是语文脑筋急转弯,语文考试都是历史背诵,一点用都没有,你出了社会就知道,社会根本没有选择题,社会要有选择题就好了,最难的是你遇到困难,你连门都找不到。我第一次这样讲的时候是女儿小学4年级,那时候我女儿听的一愣一愣的,她不明白,但是觉得我的理论和学校的不一样,很狂妄,但是她很喜欢,哈哈哈哈。 她什么时候真正明...

Nov 13, 20251 min read

被诈骗-马来西亚

最近我在国内,我老婆在马来;最近在计划搬家的,找的那个房子不包含一些必要的家具,于是我老婆就必须要买点家具的,主要是沙发和餐桌..我们本来计划是说去ikea去买,但是我老婆觉得ikea的家具不便宜,并且款式一般的,最终问了中介找了一个二手平台找找看不错的家具。 我老婆挑了两个家具的,我看了一下价格也不算便宜的,但是我老婆喜欢的,于是我就说你觉得ok那就购买吧。我还顺便问了一下,这个家具能不能线下看一下货的,但是我老婆说这货在很远的地方的,大概是300公里的一个城市的。那我就说这个包邮吗,我老婆说...

Nov 13, 20251 min read

当下和最近想做的事情

1. Current 当下 最近依然还在中国,已经回来快一个月了. 最近一直在忙着带丈母娘看病和住院的。索性一切都还在可控范围内的,丈母娘由于糖尿病控制的很差导致本身的冠心病也复发. 这次去浙江省人民医院去做了造影检查和支架植入的手术的,不过这一切都比我预估的要顺利,我就怕她由于长时间没吃药和高血糖的持续的时间太长了,会带来严重的问题,不过好在没有发生最坏的事情的。 因为做了手术,所以这段时间我和我老婆的姐姐每人轮换的陪床,不过陪床真的好累的,因为睡得很不好的,特别的累。不过好在都结束了,而且丈...

Nov 9, 20251 min read

Keep Move - 永不止步

39 posts