Redisson看门狗机制仅在未显式指定leaseTime(即leaseTime=-1或null)时自动启用,每lockWatchdogTimeout/3毫秒续期一次;若leaseTime>0(如lock(30,SECONDS)),则禁用看门狗,锁严格按租期释放。

Redisson 的 WatchDog 机制不会自动生效——它只在你**不显式传 leaseTime**(或传 -1)时才启动;一旦调用 lock(30, TimeUnit.SECONDS),看门狗立刻静默退出,锁严格按 30 秒释放,业务超时就并发。
为什么 lock() 有续期,而 lock(30, SECONDS) 没有?
是否启用 WatchDog,完全由 leaseTime 参数值决定:
-
leaseTime == -1或leaseTime == null→ 触发 WatchDog 初始化,后台线程每lockWatchdogTimeout / 3毫秒执行一次 Lua 续期脚本 -
leaseTime > 0(哪怕只是1)→ 跳过续期逻辑,锁到期即删,不等待、不重试、不通知 -
tryLock(waitTime, leaseTime, unit)同理:只要leaseTime > 0,WatchDog 就不工作
这不是 bug,是 Redisson 的明确设计:你显式声明了租期,就等于承诺“我能控制好超时”,框架不再干预。
lockWatchdogTimeout 不只是默认过期时间,它还控制续期节奏
lockWatchdogTimeout 默认为 30000(30 秒),但它同时决定两个关键行为:
- 锁的初始过期时间(仅当未指定
leaseTime时) - WatchDog 续期间隔 =
lockWatchdogTimeout / 3(默认约 10 秒)
如果业务平均耗时 90 秒,但你还用默认 30000,续期线程每 10 秒发一次请求,网络抖动一次就可能失败,锁提前释放。应改为:
config.setLockWatchdogTimeout(90_000); // 续期间隔变为 30 秒,更稳
但注意:lockWatchdogTimeout 也是死锁容忍上限——JVM 崩溃后,锁最多要等这么久才自动过期。设成 5 分钟可以,设成 2 小时就太危险。
WatchDog 失效的三个隐蔽场景
即使你没传 leaseTime,WatchDog 仍可能不工作:
-
事务内 unlock():在 Spring
@Transactional方法里调用lock.unlock(),事务提交前锁已释放,WatchDog 线程被中断,续期停止 -
手动 DEL 锁:用其他客户端(如 redis-cli)或错误 value 执行
DEL myLock,WatchDog 还在按原 value 续期,但锁早已不存在 -
锁被批量续期挤掉:当待续期锁数量超过
lockWatchdogBatchSize(默认 100),部分锁可能错过本轮续期,尤其在高并发抢锁密集期
这些情况都不会抛异常,只会静默导致锁提前释放——这也是最难排查的并发问题来源。
WatchDog 不是永动机:它依赖线程存活、网络可达、value 一致。真正关键的不是“怎么开看门狗”,而是“怎么确保它一直能踢到门”。


















