当前位置:首页 > 公众号精选 > 小林coding
[导读]废话不多说,直接上硬核。今天我们就来聊聊分布式锁。PART1.分布式锁是什么?我们的手机有锁、车有锁、家门有锁、贵重物品会锁进保险箱。可以说,锁在我们生活中无处不在,时刻保护着我们的人身财产安全。在计算机领域也一样,锁可以理解为针对某项资源使用权限的管理,它通常用来控制共享资源,...


废话不多说,直接上硬核。
今天我们就来聊聊分布式锁。

PART1.分布式锁是什么?

我们的手机有锁、车有锁、家门有锁、贵重物品会锁进保险箱。可以说,锁在我们生活中无处不在,时刻保护着我们的人身财产安全。
在计算机领域也一样,锁可以理解为针对某项资源使用权限的管理,它通常用来控制共享资源,比如一个进程内有多个线程竞争一个数据的使用权限,解决方式之一就是加锁。
那分布式锁是什么呢?
顾名思义,分布式锁就是分布式场景下的锁,比如多台不同机器上的进程,去竞争同一项资源,就是分布式锁。

PART2.分布式锁有哪些特性?


具备哪些特性的分布式锁才是一个优秀的分布式锁?我认为要从如下几方面来看:


  • 互斥性:锁的目的是获取资源的使用权,所以只让一个竞争者持有锁,这一点要尽可能保证;
  • 安全性:避免死锁情况发生。当一个竞争者在持有锁期间内,由于意外崩溃而导致未能主动解锁,其持有的锁也能够被正常释放,并保证后续其它竞争者也能加锁;
  • 对称性:同一个锁,加锁和解锁必须是同一个竞争者。不能把其他竞争者持有的锁给释放了,这又称为锁的可重入性。
  • 可靠性:需要有一定程度的异常处理能力、容灾能力。


PART3.分布式锁的常用实现方式

分布式锁,一般会依托第三方组件来实现,而利用Redis实现则是工作中应用最多的一种。


今天,就让我们从最基础的步骤开始,依照分布式锁的特性,层层递进,步步完善,将它优化到最优,让大家完整地了解如何用Redis来实现一个分布式锁


最简化版本

首先,当然是搭建一个最简单的实现方式,直接用Redis的setnx命令,这个命令的语法是:setnx key value如果key不存在,则会将key设置为value,并返回1;如果key存在,不会有任务影响,返回0。
基于这个特性,我们就可以用setnx实现加锁的目的:通过setnx加锁,加锁之后其他服务无法加锁,用完之后,再通过delete解锁,深藏功与名。


支持过期时间

最简化版本有一个问题:如果获取锁的服务挂掉了,那么锁就一直得不到释放,就像石沉大海,杳无音信。所以,我们需要一个超时来兜底。
Redis中有expire命令,用来设置一个key的超时时间。但是setnx和expire不具备原子性,如果setnx获取锁之后,服务挂掉,依旧是泥牛入海。
很自然,我们会想到,set和expire,有没有原子操作?
当然有,Redis早就考虑到了这种场景,推出了如下执行语句:set key value nx ex secondsnx表示具备setnx特定,ex表示增加了过期时间,最后一个参数就是过期时间的值。



能够支持过期时间,目前这个锁基本上是能用了。


但是存在一个问题:会存在服务A释放掉服务B的锁的可能。

加上owner

我们来试想一下如下场景:服务A获取了锁,由于业务流程比较长,或者网络延迟、GC卡顿等原因,导致锁过期,而业务还会继续进行。这时候,业务B已经拿到了锁,准备去执行,这个时候服务A恢复过来并做完了业务,就会释放锁,而B却还在继续执行。
在真实的分布式场景中,可能存在几十个竞争者,那么上述情况发生概率就很高,导致同一份资源频繁被不同竞争者同时访问,分布式锁也就失去了意义。


基于这个场景,我们可以发现,问题关键在于,竞争者可以释放其他人的锁。那么在异常情况下,就会出现问题,所以我们可以进一步给出解决方案:分布式锁需要满足谁申请谁释放原则,不能释放别人的锁,也就是说,分布式锁,是要有归属的


引入Lua

加入owner后的版本可以称得上是完善了吗?还有没有什么隐患呢?
我也不卖关子了,到这一步其实还存在一个小问题,我们完整的流程是竞争者获取锁执行任务,执行完毕后检查锁是不是自己的,最后进行释放。
流程一梳理,你们肯定明白了,执行完毕后,检查锁,再释放,这些操作不是原子化的。
可能锁获取时还是自己的,删除时却已经是别人的了。这可怎么办呢?
Redis可没有直接提供这种场景原子化的操作啊。遇事不要慌,仔细想一想,Redis是不是还有个特性,专门整合原子操作,对,就是它——Lua

Redis➕Lua,可以说是专门为解决原子问题而生。
有了Lua的特性,Redis才真正在分布式锁、秒杀等场景,有了用武之地,下面便是改造之后的流程:

其实到了这一步,分布式锁的前三个特性:称性、安全性、可靠性,就满足了。可以说是一个可用的分布式锁了,能满足大多数场景的需要。

PART4.可靠性如何保证


分布式锁的四大特性还剩下可靠性没有解决。

针对一些异常场景,包括Redis挂掉了、业务执行时间过长、网络波动等情况,我们来一起分析如何处理。

容灾考虑

前面我们谈及的内容,基本是基于单机考虑的,如果Redis挂掉了,那锁就不能获取了。这个问题该如何解决呢?
一般来说,有两种方法:主从容灾和多级部署。

主从容灾

最简单的一种方式,就是为Redis配置从节点,当主节点挂了,用从节点顶包。

但是主从切换,需要人工参与,会提高人力成本。不过Redis已经有成熟的解决方案,也就是哨兵模式,可以灵活自动切换,不再需要人工介入。

通过增加从节点的方式,虽然一定程度解决了单点的容灾问题,但并不是尽善尽美的,由于同步有时延,Slave可能会损失掉部分数据,分布式锁可能失效,这就会发生短暂的多机获取到执行权限。
有没有更可靠的办法呢?

多机部署

如果对一致性的要求高一些,可以尝试多机部署,比如Redis的RedLock,大概的思路就是多个机器,通常是奇数个,达到一半以上同意加锁才算加锁成功,这样,可靠性会向ETCD靠近。
现在假设有5个Redis主节点,基本保证它们不会同时宕掉,获取锁和释放锁的过程中,客户端会执行以下操作:
1.向5个Redis申请加锁;
2.只要超过一半,也就是3个Redis返回成功,那么就是获取到了锁。如果超过一半失败,需要向每个Redis发送解锁命令;
3.由于向5个Redis发送请求,会有一定时耗,所以锁剩余持有时间,需要减去请求时间。这个可以作为判断依据,如果剩余时间已经为0,那么也是获取锁失败;

4.使用完成之后,向5个Redis发送解锁请求。


这种模式的好处在于,如果挂了2台Redis,整个集群还是可用的,给了运维更多时间来修复。
另外,多说一句,单点Redis的所有手段,这种多机模式都可以使用,比如为每个节点配置哨兵模式,由于加锁是一半以上同意就成功,那么如果单个节点进行了主从切换,单个节点数据的丢失,就不会让锁失效了。这样增强了可靠性。
可靠性深究

是不是有RedLock,就一定能保证可靠的分布式锁?
这里我先说结论:由于分布式系统中的三大困境(简称NPC),所以没有完全可靠的分布式锁!
让我们来看看RedLock在NPC下的表现。
N:Network Delay(网络延迟)当分布式锁获得返回包的时间过长,此时可能虽然加锁成功,但是已经时过境迁,锁可能很快过期。RedLock算了做了些考量,也就是前面所说的锁剩余持有时间,需要减去请求时间如此一来,就可以一定程度解决网络延迟的问题。
P:Process Pause(进程暂停)比如发生GC,获取锁之后GC了,处于GC执行中,然后锁超时。


其他锁获取,这种情况几乎无解。这时候GC回来了,那么两个进程就获取到了同一个分布式锁。


也许你会说,在GC回来之后,可以再去查一次啊?
这里有两个问题,首先你怎么知道GC回来了?这个可以在做业务之前,通过时间,进行一个粗略判断,但也是很吃场景经验的;第二,如果你判断的时候是ok的,但是判断完GC了呢?这点RedLock是无法解决的
C:Clock Drift(时钟漂移)
如果竞争者A,获得了RedLock,在5台分布式机器上都加上锁。为了方便分析,我们直接假设5台机器都发生了时钟漂移,锁瞬间过期了。这时候竞争者B拿到了锁,此时A和B拿到了相同的执行权限。
根据上述的分析,可以看出,RedLock也不能扛住NPC的挑战,因此,单单从分布式锁本身出发,完全可靠是不可能的。要实现一个相对可靠的分布式锁机制,还是需要和业务的配合,业务本身要幂等可重入,这样的设计可以省却很多麻烦。

PART5.复盘

我们围绕互斥性、安全性、对称性层层递进,实现了一个Redis分布式锁,这样的架构在大多数业务场景都是完全够用的。


同时,我们也针对可靠性,探讨了主从容灾、Red Lock等解决方案,并分析了NPC异常场景,了解到分布式锁在什么情况会失去作用,这些知识在实际的业务中都非常实用,能够在实际开发中做出正确的决策。


建议对分布式锁不要强依赖,没有绝对可靠的分布式锁,分布式锁需要与业务的联动配合更加切实可行,脱离了业务,就是空中楼阁,不着实地。


图解 Reids 系列文章
  • 先更新数据库,还是先更新缓存?

  • 主从复制

  • RDB 和 AOF 读者问题答疑

  • RDB 快照

  • AOF 日志

  • 缓存雪崩、击穿、穿透



本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭