Redis分布式锁“自动失效”主因是看门狗未启动或中断,核心判断标准为lock.tryLock()是否传leaseTime参数:传入正数(如10秒)则禁用看门狗,仅-1或不指定才启用;且看门狗绑定获取锁的线程,跨线程执行会导致续期失效。

Redis分布式锁在Spring Boot中“自动失效”,绝大多数情况不是Redis挂了、也不是网络断了,而是看门狗机制根本没启动,或者启动了但被中途掐断。核心判断标准只有一条:lock.tryLock() 调用时是否传了 leaseTime 参数。
为什么 lock.tryLock(10, TimeUnit.SECONDS) 会禁用看门狗
这个调用看似只是加了个超时,实则彻底关闭了Redisson的自动续期能力。因为leaseTime明确告诉Redisson:“我就只要这10秒,到期就删,别管我业务跑没跑完”。看门狗只在leaseTime为-1(或未指定)时才激活。
-
lock.tryLock()→ 启动看门狗,默认30秒续期,每10秒检查一次 -
lock.tryLock(10, TimeUnit.SECONDS)→ 禁用看门狗,10秒后无条件释放锁 -
lock.lock(10, TimeUnit.SECONDS)→ 同样禁用看门狗,且不带等待逻辑,失败直接抛异常
线程切换导致看门狗“失联”的真实场景
看门狗不是全局守护进程,它绑定在**获取锁的那个线程**上。一旦业务逻辑被切到其他线程执行,原线程结束,看门狗随之终止,锁会在30秒后过期——哪怕业务还在跑。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- @Async 方法里调用
lock.tryLock():锁在线程A获取,但业务在线程B执行,线程A退出后看门狗停摆 - CompletableFuture.supplyAsync() + thenAccept() 链式调用:锁在主线程获取,后续回调在ForkJoinPool线程执行
- 手动提交到自定义线程池:必须确保
lock.unlock()也在同一池中同一线程调用,否则isHeldByCurrentThread()返回false,unlock静默失败
lockWatchdogTimeout 配置值改大反而更危险
很多人以为把 lockWatchdogTimeout: 60000 改成60秒就能撑住长任务,这是误解。这个参数不是“业务最大容忍时间”,而是“锁续期目标时长”——看门狗每次续期都设为这个值,但它检测间隔仍是 lockWatchdogTimeout / 3(默认10秒)。如果业务卡在某个IO上超过60秒,而看门狗线程本身因GC暂停或调度延迟没及时续上,锁就丢了。
- 生产环境建议保持默认
30000(30秒),它经过大量压测验证,在可靠性与资源开销间取得平衡 - 真正需要支撑长任务的,应拆分业务逻辑,或用状态机+幂等设计替代长时间持锁
- 修改该值必须同步调整
renewalInterval,否则检测频率跟不上,续期可能错过窗口
最常被忽略的一点是:看门狗是否生效,和你有没有写 try/finally 无关,而取决于锁获取与业务执行是否发生在**同一个线程栈帧内**。跨线程、跨上下文传递锁对象,本质上是在欺骗看门狗——它认的是线程ID,不是变量名。

















