scheduleExpirationRenewal 方法处理了ExpirationEntry和如果出现异常则取消看门狗,具体看门狗逻辑在 renewExpiration 方法中
private void renewExpiration() {ExpirationEntry ee = EXPIRATION_RENEWAL_MAP.get(getEntryName());if (ee == null) {return;}// 创建延时任务,延时时间是internalLockLeaseTime / 3Timeout task = commandExecutor.getConnectionManager().newTimeout(new TimerTask() {@Overridepublic void run(Timeout timeout) throws Exception {ExpirationEntry ent = EXPIRATION_RENEWAL_MAP.get(getEntryName());if (ent == null) {return;}Long threadId = ent.getFirstThreadId();if (threadId == null) {return;}// lua脚本判断,如果锁存在,则续期并返回true,不存在则返回falseCompletionStage<Boolean> future = renewExpirationAsync(threadId);future.whenComplete((res, e) -> {if (e != null) {log.error("Can't update lock " + getRawName() + " expiration", e);EXPIRATION_RENEWAL_MAP.remove(getEntryName());return;}if (res) {// 锁续期成功,则再启动一个延时任务,继续监测renewExpiration();} else {// 取消看门狗cancelExpirationRenewal(null);}});}}, internalLockLeaseTime / 3, TimeUnit.MILLISECONDS);ee.setTimeout(task);}
Timeout 是一个延时任务,延时 internalLockLeaseTime / 3 时间执行 。任务的内容主要是通过 renewExpirationAsync 方法对锁进行续期,如果续期失败(解锁了、锁到期等),则取消看门狗,如果续期成功,则递归 renewExpiration 方法,继续创建延时任务 。
internalLockLeaseTime 也就是 lockWatchdogTimeout 参数,默认是 30 秒 。
总结本文介绍了Redisson的加锁、解锁、看门狗机制,以及对Redis发布订阅机制的应用 。因为篇幅有限,很多细节聊得不够深入 。此外Redisson的异步机制、对Netty的使用等都是很值得水文章的 。
参考资料
万字长文带你解读Redisson分布式锁的源码 - 知乎 (zhihu.com)
Redis分布式锁-这一篇全了解(Redission实现分布式锁完美方案)
经验总结扩展阅读
- 源码级深度理解 Java SPI
- Dubbo-聊聊通信模块设计
- 【lwip】10-ICMP协议&源码分析
- 【lwip】09-IPv4协议&超全源码实现分析
- 京东云开发者|经典同态加密算法Paillier解读 - 原理、实现和应用
- 从BeanFactory源码看Bean的生命周期
- 详解AQS中的condition源码原理
- 实例解读丨关于GaussDB ETCD服务异常
- 【lwip】08-ARP协议一图笔记及源码实现
- 【lwip】07-链路层收发以太网数据帧源码分析