本文最后更新于154 天前,其中的信息可能已经过时,如有错误请发送邮件到moping1019@foxmail.com
在分布式系统中,Redisson提供的分布式锁是解决并发问题的常用方案。但你是否遇到过这样的场景:业务逻辑还未执行完毕,锁却因超时被自动释放?这可能导致多个客户端同时操作共享资源,引发数据不一致问题。Redisson的看门狗(Watchdog)机制正是为解决这一痛点而设计,它通过自动续期功能,确保锁在业务执行期间持续有效。
一、看门狗机制的核心作用
看门狗机制的核心目标是:避免锁在业务逻辑未完成时被提前释放。
当客户端获取锁后,若未显式设置锁的过期时间(leaseTime),Redisson会自动启动看门狗机制。它通过后台定时任务,定期刷新锁的过期时间(默认每10秒续期一次,每次将锁的过期时间重置为30秒),从而延长锁的有效期。只有当客户端主动释放锁或宕机时,续期才会停止。
关键特性:
- 自动续期:仅对未设置过期时间的锁生效。
- 安全释放:客户端正常释放锁时,看门狗会取消续期任务。
- 防死锁:客户端宕机后,锁会在30秒后自动释放。

二、工作原理深度解析
1. 触发条件
看门狗机制仅在以下情况下启动:
- 客户端调用
lock.lock()(未指定超时时间),而非lock.lock(10, TimeUnit.SECONDS)。 - 锁的默认过期时间
internalLockLeaseTime为30秒(可通过config.setLockWatchdogTimeout(15000)调整)。

2. 续期流程
看门狗的续期操作基于Netty时间轮实现,核心步骤如下:
(1)启动定时任务
客户端获取锁后,调用scheduleExpirationRenewal()方法:
- 创建
ExpirationEntry对象,存储锁的线程ID等信息。 - 通过
EXPIRATION_RENEWAL_MAP.putIfAbsent()注册续期条目。 - 首次注册成功则触发
renewExpiration()启动续期任务。
(2)定期刷新过期时间
renewExpiration()方法的核心逻辑:
// 每 internalLockLeaseTime / 3 毫秒(默认10秒)执行一次
commandExecutor.getServiceManager().newTimeout(timeout -> {
// 1. 检查续期条目是否存在
ExpirationEntry entry = EXPIRATION_RENEWAL_MAP.get(getEntryName());
if (entry == null) return;
// 2. 异步执行续期脚本
renewExpirationAsync(entry.getFirstThreadId()).whenComplete((res, e) -> {
if (res) {
renewExpiration(); // 续期成功,递归调度下次任务
} else {
cancelExpirationRenewal(null); // 续期失败,取消任务
}
});
}, 10, TimeUnit.SECONDS);
(3)Lua脚本实现原子续期
续期操作通过Redis Lua脚本保证原子性:
-- 检查锁是否存在,若存在则重置过期时间为30秒
if redis.call('hexists', KEYS, ARGV) == 1 then
redis.call('pexpire', KEYS, ARGV); -- 重置而非累加
return 1;
end;
return 0;
注意:续期是将过期时间重置为30秒,而非在原基础上增加。

3. 释放锁的联动
- 主动释放:调用
unlock()时,无论成功与否,均触发cancelExpirationRenewal()取消续期任务。 - 异常中断:线程被中断时,同样取消续期。
三、容错与异常处理

1. 客户端宕机
- 定时任务终止,锁在30秒后自动过期释放,避免死锁。
2. 紧急处理方案
- 手动删除Key:通过Redis CLI直接删除锁Key(需谨慎操作)。
- 调整超时时间:
Config config = new Config();
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
config.setLockWatchdogTimeout(15000); // 修改续期超时时间为15秒
RedissonClient redisson = Redisson.create(config);
四、源码级注意事项
- 续期本质:重置过期时间而非累加,避免时间无限延长。
- 资源清理:解锁时强制取消续期任务,防止内存泄漏。
- 线程安全:多个线程竞争同一锁时,仅首个线程启动续期任务,其他线程共享条目。
- 异常兜底:续期失败时(如Redis通信异常),立即取消任务并清除记录。
五、典型应用场景

| 场景 | 是否适用看门狗 | 说明 |
| 长耗时任务(如文件处理) | ✅ | 业务执行时间不确定,需自动续期 |
| 短时操作(如缓存更新) | ❌ | 应显式设置leaseTime,避免无效续期 |
| 高并发抢锁 | ✅ | 结合tryLock()与看门狗,平衡安全性与灵活性 |
六、总结
Redisson看门狗机制通过动态续期解决了分布式锁的超时释放问题,其设计兼顾了安全性(防死锁)、性能(异步续期)与可靠性(异常兜底)。开发者需注意:
- 仅对无超时时间的锁生效,显式设置
leaseTime会禁用看门狗。 - 合理调整
lockWatchdogTimeout,避免续期频率过高或过低。 - 生产环境监控锁状态,结合日志分析续期失败场景。

通过深入理解看门狗机制,开发者可更高效地构建高可靠的分布式系统,避免因锁管理不当引发的并发冲突。



-697x1024.png)


