再探 redis 分布式锁

文章探讨了Redis分布式锁在主从切换时的潜在问题,介绍了Redlock的原理和设计,以及马丁对其的质疑,特别是关于时钟同步、网络延迟和GC对锁安全的影响。Redis作者回应了关于时钟误差和释放锁策略的讨论,并提到fencingtoken作为替代方案。最后提及了Spring框架在企业中的重要性。
摘要由CSDN通过智能技术生成

return 0

end

到这里,一个单节点的 redis 锁便完成了它的使命。

但是,分布式到这里还没铺开呢!!!


主从切换


我们在使用 Redis 时,一般会采用主从集群 + 哨兵的模式部署。当主从发生切换的时候,这个分布式锁依旧安全么?

在这里插入图片描述

1、客户端1在主库上上锁。

2、主库宕机,setnx 命令还未到达从库。

3、从库被哨兵提升为新主库。

4、该锁在新主库上查不到,则可以由另一个客户端上锁。

于是又开始俄罗斯套娃了。

为此,Redis 的作者提出一种解决方案,就是我们经常听到的 Redlock(红锁)。


Redlock 红锁


Redlock 的方案基于 2 个前提:

1、不再需要部署从库和哨兵实例,只部署主库。

2、但主库要部署多个,官方推荐至少 5 个实例。

问:不做主从,那万一某个库宕机了,数据不就都丢了吗?

答:丢就丢了呗,本来就不是用来存数据的。

具体流程如下:

1、客户端先获取当前时间戳T1。

2、客户端依次向这 5 个 Redis 实例发起加锁请求,且每个请求会设置超时时间(毫秒级,要远小于锁的有效时间),

如果某一个实例加锁失败(包括网络超时、锁被其它人持有等各种异常情况),就立即向下一个 Redis 实例申请加锁。

3、如果客户端从 >=3 个(大多数)以上 Redis 实例加锁成功,则再次获取「当前时间戳T2」,如果 T2 - T1 < 锁的过期时间,此时,认为客户端加锁成功,否则认为加锁失败。

4、加锁成功,去操作共享资源。

5、加锁失败,向「全部节点」发起释放锁请求。

问:我也不贪心,我 5 个实例来共同竞争,需要竞争多少遍(失败一遍就要全部释放)?

答:emmm…emmm…emmm…(容我三思)(思不出来)

问:为什么要在多个节点上上锁?

答:防止某些个节点因为各种原因不能提供服务,且没来得及恢复。

问:为什么释放锁,要操作所有节点?

答:无则加勉,有则改之。

二三那俩问题是网上提的比较多的,问题一是我自己提的,结果自己答不上来。。。


分布式系统专家马丁的质疑


马丁写了一篇文章(How to do distributed locking),表达了自己对于红锁的质疑。在他的文章中主要阐述了四个观点:

1、分布式锁的目的是什么?

2、锁在分布式系统中会遇到的问题。

3、假设时钟正确是不合理的。

4、提出 fencing token 的方案,保证正确性。

我们一一来看:


1、分布式锁的目的。

他认为有两个目的:

1、效率。

2、正确性。

如果是为了效率,那么单机版的 Redis 就可以了,即使偶尔锁失效,也是可以理解的。

如果是为了正确性,马丁认为 Redlock 根本达不到分布式安全的要求,依旧存在锁失效的问题。

(其实我没想明白上锁提升效率,是什么情况。)


2、锁在分布式系统中会遇到的问题

Martin 表示,一个分布式系统,更像一个复杂的「野兽」,存在着你想不到的各种异常情况。

这些异常场景主要包括三大块,这也是分布式系统会遇到的三座大山:NPC。

N:Network Delay,网络延迟

P:Process Pause,进程暂停(GC)

C:Clock Drift,时钟漂移

Martin 用一个进程暂停(GC)的例子,指出了 Redlock 安全性问题:

1、客户端 1 请求锁定节点 A、B、C、D、E

2、客户端 1 的拿到锁后,进入 GC(时间比较久)

3、所有 Redis 节点上的锁都过期了

4、客户端 2 获取到了 A、B、C、D、E 上的锁

5、客户端 1 GC 结束,认为成功获取锁

6、客户端 2 也认为获取到了锁,发生「冲突」

Martin 认为,GC 可能发生在程序的任意时刻,而且执行时间是不可控的。

当然,即使是使用没有 GC 的编程语言,在发生网络延迟、时钟漂移时,也都有可能导致 Redlock 出现问题,这里 Martin 只是拿 GC 举例。


3、假设时钟正确是不合理的。

客户端C1获得了对节点A、B、c的锁定,由于网络问题,法到达节点D和节点E

节点C上的时钟向前跳,导致锁提前过期

客户端C2在节点C、D、E上获得锁定,由于网络问题,无法到达A和B

客户端C1和客户端C2现在都认为他们自己持有锁

前跳应该是不至于了,不过系统时钟是存在误差的,可以看我前面发的那篇:

计算机时钟是如何运行的?


4、提出 fencing token 的方案,保证正确性

1、客户端在获取锁时,锁服务可以提供一个「递增」的 token

2、客户端拿着这个 token 去操作共享资源

3、共享资源可以根据 token 拒绝「后来者」的请求

这样一来,无论 NPC 哪种异常情况发生,都可以保证分布式锁的安全性,因为它是建立在「异步模型」上的。

他还表示,一个好的分布式锁,无论 NPC 怎么发生,可以不在规定时间内给出结果,但并不会给出一个错误的结果。也就是只会影响到锁的「性能」(或称之为活性),而不会影响它的「正确性」。


Redis 作者 Antirez 的反驳


在 Redis 作者的文章中,重点有 3 个:

1)解释时钟问题。

Redis 作者表示,Redlock 并不需要完全一致的时钟,只需要大体一致就可以了,允许有「误差」。

(不晓得哦,前面不是要计算时间吗?)

2)解释网络延迟、GC 问题

Redis 作者强调:如果在 1-3 发生了网络延迟、进程 GC 等耗时长的异常情况,那在第 3 步 T2 - T1,是可以检测出来的,如果超出了锁设置的过期时间,那这时就认为加锁会失败,之后释放所有节点的锁就好了!

(但是如果是锁已经拿到手上了呢,拿到手之后GC)

  1. 质疑 fencing token 机制

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后的话

无论是哪家公司,都很重视Spring框架技术,重视基础,所以千万别小看任何知识。面试是一个双向选择的过程,不要抱着畏惧的心态去面试,不利于自己的发挥。
同时看中的应该不止薪资,还要看你是不是真的喜欢这家公司,好了希望这篇文章对大家有帮助!

部分截图:
在这里插入图片描述

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
faed303032d36.jpg" alt=“img” style=“zoom: 33%;” />

最后的话

无论是哪家公司,都很重视Spring框架技术,重视基础,所以千万别小看任何知识。面试是一个双向选择的过程,不要抱着畏惧的心态去面试,不利于自己的发挥。
同时看中的应该不止薪资,还要看你是不是真的喜欢这家公司,好了希望这篇文章对大家有帮助!

部分截图:
[外链图片转存中…(img-0x0mUzEN-1713533522012)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值