redis面试(八)watchdog看门狗代码逻辑

某个客户端上锁了之后,一直比如过了5分钟,10分钟,都没释放掉这个锁,那么你觉得会怎么样呢?锁对应的key刚开始的生存周期其实就是30秒而已,难道是默认情况下30秒后这个锁就自动释放???

lock watchdog,你对anyLock这个key加锁了以后,然后后台有一个定时调度的一个watchdog任务,这个任务的话呢其实就是每隔一定时间,10秒左右,延长一下anyLock这个key的生存周期,重新延长到30秒

只要你的这个lock没有释放掉,那么这个后台的watchdog他就会不断的去重复延长这个key的生存周期,对应的就是你的客户端长期的5分钟,10分钟,30分钟,一直持有了某一个key对应的分布式锁

首先从源码的层面,带着大家来看一下,如果你成功的对某个key加锁了之后,后台的定时调度任务(lock watchdog)是如何每隔10秒钟去延长一下那个key的生存时间的?

RFuture ttlRemainingFuture = tryLockInnerAsync()

我们上一节可以知道,tryLockInnerAsync这个方法中返回的是lua脚本执行之后,得到的这个key剩余的存在时间,不传的话默认是3000毫秒,也就是3秒钟。

那看下面的addListener()逻辑,这一看就是要加一个监听。

首先(!future.isSuccess()) 先判断上面加锁是否成功,如果不成功的话就直接返回不用管了,成功的话就取出来当前的剩余有效期,有效期也不为空的话,就去执行监听逻辑

还有一个判断,是返回值是否为null,如果为null的话才是加锁成功,不为null的话是失败

scheduleExpirationRenewal()方法 按照字面意思看的话,就是时间 过期 更新 。很明显,这里一定和看门狗逻辑有关系。 我们去看看里面的逻辑

第一行很简单expirationRenewalMap.containsKey(getEntryName())

就是判断一下expirationRenewalMap 中是否存在这样一个key,如果不存在的话再执行下面的逻辑。

第一次进来肯定是不包含的。

继续往下,就是开启了一个定时调度任务,传入了一个TimerTask对象和 internalLockLeaseTime

internalLockLeaseTime默认是30000毫秒也就是 30秒,除以3 就是10秒

意思是这个TimerTask对象中的逻辑要等待10s中再执行

那执行TimerTask.run()方法的时候,先执行RFuture future = renewExpirationAsync(threadId);

这行代码,renewExpirationAsync()方法,更新过期时间

"if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " +

"redis.call('pexpire', KEYS[1], ARGV[1]); " +

"return 1; " +

"end; " +

"return 0;",

判断这个锁是否还存在,如果存在的话,将过期时间更新为30s。

(PS: 题外话 果然,这里只更新了过期时间,并没有更新原本的value值)

当前情况是,已经等待了10s,这个线程还持有这把锁,有效期只剩下20s,那现在看锁还存在,就更新过期时间为30s。

再回到之前的逻辑中看,延长完有效期,如果成功的话,会往下执行,再次进入本方法scheduleExpirationRenewal()

也就是说会再等待10s中,然后再判断锁是否存在,存在的话更新过期时间为30s,不存在的话,从这个方法中返回。执行下面的判断逻辑

将这个锁放入expirationRenewalMap中,下次再进入scheduleExpirationRenewal()方法,判断map中有值,就不会再执行更新过期时间的方法了。

这就是看门狗的一个不断更新逻辑,这时候有个问题,就是如果主机宕机了怎么释放锁?

很简单,如果宕机了,那么这台主机上的这个看门狗逻辑就不会再执行了,那么过30s之后,这个锁就会自动过期,其他主机就可以获取到这把锁了。

总结

就是在加锁之后,注册一个线程监听,每10s循环判断线程是否还存在。如果监听到线程不在了,就不再执行,如果锁缓存不在了,就不在延长时间。

相关推荐
你的微笑,乱了夏天11 分钟前
linux centos 7 安装 mongodb7
数据库·mongodb
工业甲酰苯胺22 分钟前
分布式系统架构:服务容错
数据库·架构
独行soc1 小时前
#渗透测试#漏洞挖掘#红蓝攻防#护网#sql注入介绍08-基于时间延迟的SQL注入(Time-Based SQL Injection)
数据库·sql·安全·渗透测试·漏洞挖掘
White_Mountain2 小时前
在Ubuntu中配置mysql,并允许外部访问数据库
数据库·mysql·ubuntu
Code apprenticeship2 小时前
怎么利用Redis实现延时队列?
数据库·redis·缓存
百度智能云技术站2 小时前
广告投放系统成本降低 70%+,基于 Redis 容量型数据库 PegaDB 的方案设计和业务实践
数据库·redis·oracle
装不满的克莱因瓶2 小时前
【Redis经典面试题六】Redis的持久化机制是怎样的?
java·数据库·redis·持久化·aof·rdb
GISer_Jing3 小时前
2025前端面试热门题目——计算机网络篇
前端·计算机网络·面试
m0_748245523 小时前
吉利前端、AI面试
前端·面试·职场和发展
梦想平凡3 小时前
PHP 微信棋牌开发全解析:高级教程
android·数据库·oracle