redis面试(十六)公平锁释放和排队加锁

锁释放

RedissonFairLock.unlockInnerAsync()方法

这和加锁的逻辑没有太大区别

也就是说在客户端A他释放锁的时候,也会走while true的脚本逻辑,看一下有序集合中的元素的timeout时间如果小于了当前时间,就认为他的那个排队就过期了,就删除他,让他后面重新尝试获取锁的时候重排序

while true的逻辑,比如说客户端B或者客户端C,他们用的是tryAcquire()方法,他们其实设置了一个获取锁超时的时间,比如说他们在队列里排队,但是尝试获取锁超过了20秒,人家就不再尝试获取锁了

此时他们还是在队列和有序集合里占了一个坑位,while true的逻辑就可以保证说剔除掉这种不再尝试获取锁的客户端,有序集合里的timeout分数就不会刷新了,随着时间的推移,肯定就会剔除掉他

如果客户端宕机了,也会导致他就不会重新尝试来获取锁,也就不会刷新有序集合中的timeout分数,不会延长timeout分数,while true的逻辑也可以剔除掉这种宕机的客户端在队列里的占用

因为网络延迟等各种因素在里面,可能会在等待锁时间过长的时候,触发各个客户端的排队的顺序的重排序,有的客户端如果在队列里等待时间过长了,那么其实是可以触发一次队列的重排序的

他在这里发布一个锁被释放的消息,肯定在他的源码中是有一些人是订阅了这个释放锁的消息的,此时他们就可以得到一个锁被释放掉的通知

排队加锁

如果客户端A释放了锁,删除了锁key之后,客户端B和客户端C是如何按照顺序依次加锁的。

要记得,刚才我们经历了队列重拍,排在队头的是客户端C,后面是客户端B

假设锁被释放掉了之后,如果客户端B先来尝试加锁

客户端B加锁失败

10:00:40,锁已经被释放了,客户端B来尝试重新加锁

10:01:04 <= 10:00:40?不成立

exists anyLock = 0,当前锁不存在;exists redisson_lock_queue:{anyLock} = 0,要不然就是队列不存在,但是现在队列是存在的;lindex redisson_lock_queue:{anyLock} 0 = UUID_02:threadId_02,队列存在,但是排在队列头部的不是客户端B的线程

所以上面整体条件不成立,无法加锁

ttl = 10:01:04 - 10:00:40 = 24000毫秒

timeout = 24000 + 10:00:40 + 5000 = 10:01:09

zadd指令,刷新一下客户端B在有序集合中的timeout分数,10:01:09

哪怕是锁释放掉了,其他各个客户端来尝试重新加锁也是不行的,因为此时排在队头的不是这个客户端也不行,此时只会重新计算timeout分数刷新一下有序集合中的timeout分数罢了

客户端C加锁成功

此时客户端C来尝试加锁会如何?

anyLock锁key不存在的;队列是存在的;队列的队头就是客户端C,所以此时加锁的条件成立了,进入加锁的逻辑

lpop redisson_lock_queue:{anyLock},将队列中的第一个元素弹出来

zrem redisson_lock_timeout:{anyLock} UUID_03:threadId_03,将有序集合中的客户端C的线程id的元素给删除掉

hset anyLock UUID_03:threadId_03 1,加锁

pexpire anyLock 30000,设置生存时间为30000毫秒

完成加锁,而且客户端C从队列中出队,此时排在队头的就是客户端B了

获取锁超时,其他客户端获取不到锁,一定会在java代码里进入一个while true死循环,一定时间内没有获取到锁,就返回false标识获取锁失败,过了一段时间,只要没有刷新有序集合中的timeout分数,就会自然被lua脚本里的while true逻辑给清理掉

超时自动释放锁,不会开启lock watchdog后台定时调度的任务

相关推荐
了一li1 小时前
Qt中的QProcess与Boost.Interprocess:实现多进程编程
服务器·数据库·qt
码农君莫笑1 小时前
信管通低代码信息管理系统应用平台
linux·数据库·windows·低代码·c#·.net·visual studio
别致的影分身2 小时前
使用C语言连接MySQL
数据库·mysql
京东零售技术3 小时前
“慢”增长时代的企业数据体系建设:超越数据中台
数据库
sdaxue.com3 小时前
帝国CMS:如何去掉帝国CMS登录界面的认证码登录
数据库·github·网站·帝国cms·认证码
o(╥﹏╥)4 小时前
linux(ubuntu )卡死怎么强制重启
linux·数据库·ubuntu·系统安全
阿里嘎多学长4 小时前
docker怎么部署高斯数据库
运维·数据库·docker·容器
Yuan_o_5 小时前
Linux 基本使用和程序部署
java·linux·运维·服务器·数据库·后端
Sunyanhui15 小时前
牛客网 SQL36查找后排序
数据库·sql·mysql
老王笔记5 小时前
MHA binlog server
数据库·mysql