看门狗失效主因是显式指定leaseTime或未在finally中调用unlock();leaseTime>0时看门狗不启动,仅leaseTime=-1时每10秒续期重置TTL为30秒。

看门狗失效,八成是因为你显式指定了 leaseTime,或者没在 finally 块里调用 unlock()。
显式传入 leaseTime 会直接禁用看门狗
Redisson 的看门狗只在「未指定锁租期」时启动。只要你在加锁时写了具体时间,比如 lock.lock(10, TimeUnit.SECONDS) 或 tryLock(5, 10, TimeUnit.SECONDS),源码里就会跳过续期初始化逻辑。
-
leaseTime == -1(或不传)→ 启动看门狗,默认每 10 秒续一次,TTL 重置为 30 秒 -
leaseTime > 0→ 看门狗完全不启动,锁到期即删,不管业务是否还在跑 - 常见误用:
tryLock(waitTime, leaseTime, unit)的第二个参数就是leaseTime,不是“最长等待时间”
unlock() 没进 finally 是静默失效的温床
看门狗续期的前提是:锁仍被当前线程持有,且线程还活着。如果业务抛异常、提前 return、或 unlock() 被写在 if 分支里没执行到,锁就一直挂着——但你以为它还在续期?其实不会。
- 看门狗只在锁被成功获取后才启动;一旦
unlock()被调用,续期任务立即取消 - 没进
finally→ 锁没释放 → 看门狗持续续期 → 其他客户端永远抢不到锁 → 表现为“死锁”,而非“失效” - 更危险的是:锁被意外释放(比如误删 key),而你的代码以为还在持有,继续执行临界区 → 数据错乱
检查 Redis 中实际 TTL 是否在动态更新
别只信日志或代码逻辑,直接查 Redis 状态才是真相。用 PTTL 看锁 key 的剩余毫秒数,连续观察几次:
- 如果 TTL 始终卡在某个值(比如 30000)不动 → 看门狗可能根本没启动(
leaseTime问题) - 如果 TTL 从 30000 快速跌到 0 → 续期请求失败(网络/Redis 故障,或 Netty 线程池耗尽)
- 如果 TTL 在 28000–30000 之间小幅波动 → 正常续期中(注意:不是固定每 10 秒跳变,而是每次续期后重置为 30 秒)
- 命令示例:
PTTL your_lock_key,配合HEXISTS your_lock_key any_thread_id验证持有者
真正难排查的,是那些「看起来在续期、其实已失效」的场景:比如 GC 停顿导致某次续期延迟了 12 秒,下一次续期任务就被推后,中间出现 2 秒空窗 —— 这时候 Redis 已删 key,但你的线程还没感知到。











