return 0
end
到这里,一个单节点的 redis 锁便完成了它的使命。
但是,分布式到这里还没铺开呢!!!
我们在使用 Redis 时,一般会采用主从集群 + 哨兵的模式部署。当主从发生切换的时候,这个分布式锁依旧安全么?
1、客户端1在主库上上锁。
2、主库宕机,setnx 命令还未到达从库。
3、从库被哨兵提升为新主库。
4、该锁在新主库上查不到,则可以由另一个客户端上锁。
于是又开始俄罗斯套娃了。
为此,Redis 的作者提出一种解决方案,就是我们经常听到的 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 作者的文章中,重点有 3 个:
1)解释时钟问题。
Redis 作者表示,Redlock 并不需要完全一致的时钟,只需要大体一致就可以了,允许有「误差」。
(不晓得哦,前面不是要计算时间吗?)
2)解释网络延迟、GC 问题
Redis 作者强调:如果在 1-3 发生了网络延迟、进程 GC 等耗时长的异常情况,那在第 3 步 T2 - T1,是可以检测出来的,如果超出了锁设置的过期时间,那这时就认为加锁会失败,之后释放所有节点的锁就好了!
(但是如果是锁已经拿到手上了呢,拿到手之后GC)
- 质疑 fencing token 机制
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
最后的话
无论是哪家公司,都很重视Spring框架技术,重视基础,所以千万别小看任何知识。面试是一个双向选择的过程,不要抱着畏惧的心态去面试,不利于自己的发挥。
同时看中的应该不止薪资,还要看你是不是真的喜欢这家公司,好了希望这篇文章对大家有帮助!
部分截图:
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
faed303032d36.jpg" alt=“img” style=“zoom: 33%;” />
最后的话
无论是哪家公司,都很重视Spring框架技术,重视基础,所以千万别小看任何知识。面试是一个双向选择的过程,不要抱着畏惧的心态去面试,不利于自己的发挥。
同时看中的应该不止薪资,还要看你是不是真的喜欢这家公司,好了希望这篇文章对大家有帮助!
部分截图:
[外链图片转存中…(img-0x0mUzEN-1713533522012)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!