Redisson看门狗机制默认启用,仅当leaseTime为-1或null时启动自动续期;若设为正数(如lock(30, SECONDS)),则禁用看门狗,锁严格按设定时间过期,无法感知业务是否完成,易致超卖或重复执行。

Redisson 的看门狗机制不是“可选功能”,而是解决高并发下锁提前释放问题的默认保障——但它只在你没显式设 leaseTime 时才启动;一旦传了正数,它就彻底关闭,锁退化为静态过期,高并发下的超卖、重复执行风险立刻回归。
为什么 lock() 能自动续期,而 lock(30, SECONDS) 不能
是否启用看门狗,完全由 leaseTime 参数值决定:
-
leaseTime == -1或leaseTime == null→ 启动后台续期线程,每lockWatchdogTimeout / 3毫秒执行一次 Lua 续约脚本 -
leaseTime > 0(哪怕只是1)→ 直接跳过续期逻辑,锁严格按该值过期,不感知业务是否完成 - 常见误用:
tryLock(5, 60, SECONDS)看似“等 5 秒、锁 60 秒”,实则禁用看门狗;若业务耗时 65 秒,第 60 秒锁就失效,其他线程立即抢入
lockWatchdogTimeout 配置不当会引发续期失败或死锁容忍失控
这个参数不只是“默认锁过期时间”,它同时控制续期间隔和客户端崩溃后锁的最大残留时间:
- 默认值
30000(30 秒)→ 续期间隔 ≈ 10 秒;适合平均耗时 ≤ 20 秒的业务 - 若业务平均耗时 90 秒,建议设为
120000(2 分钟)→ 续期间隔升至 40 秒,降低 Redis 压力与网络抖动导致的续期失败概率 - 但不能无限制调大:JVM 崩溃后,锁最多要等
lockWatchdogTimeout时间才自动释放;设成 1 小时,就等于接受长达 1 小时的潜在死锁窗口 - 该值需在
Config初始化时全局配置,无法 per-lock 覆盖
看门狗在哪些真实场景下会静默失效
它依赖客户端线程存活 + Redis 连通性,以下情况它救不了你,必须靠架构兜底:
- 业务线程被
Thread.sleep(60000)卡住,且进程被kill -9强杀 → 看门狗线程消失,锁会在lockWatchdogTimeout后过期,但无任何通知;需配合幂等设计与失败告警 - Redis 集群脑裂,客户端连到从节点(只读)→ 续约 Lua 脚本返回
0,后续所有操作失败;RedisTimeoutException会被抛出,但不会自动重试或降级 - 运维误执行
FLUSHDB或手动DEL锁 key → 看门狗仍在尝试续约,但每次返回0,最终因连续失败停止任务,锁已丢失却无感知 - 在
@Transactional方法内加锁 →unlock()在事务提交前触发,看门狗立即停,锁瞬间失效;必须把锁生命周期完整移出事务边界
真正容易被忽略的是:看门狗续期靠 Lua 脚本原子校验 GET + PEXPIRE,它只认当前锁 value(即线程 ID)。一旦你用别的客户端删锁,或用错 value 调 unlock(),看门狗还在傻等,但锁早已不存在——这种“假持有”状态,日志里几乎不报错,只能靠 TTL 和业务行为交叉验证。











