Redisson的WatchDog机制默认开启,仅在无参lock()或leaseTime=-1时生效,每10秒自动续期至30秒;指定leaseTime则禁用WatchDog,锁到期即释放。

Redisson 的锁自动续期(WatchDog)不是可选功能,而是默认开启的保底机制;你不用手动调用,但必须理解它何时生效、何时失效、以及哪些操作会关闭它。
为什么 lock.lock() 之后锁不会过期?
Redisson 默认使用 lock.lock()(无参)时,底层会启动一个后台 WatchDog 线程,每 10 秒检查一次该锁是否仍被当前线程持有,并自动将 Redis 中对应 key 的 TTL 刷新为 30 秒(默认值)。这个行为只对无参 lock() 或显式传入 leaseTime = -1 的情况生效。
常见误区是以为“只要加了锁就永远有效”——其实 WatchDog 只在以下条件下持续工作:
- 锁是通过
lock.lock()或lock.lock(-1, TimeUnit.SECONDS)获取的(即未指定固定租约时间) - 持有锁的线程还活着,且未被中断
- RedissonClient 没有被关闭,连接正常
- 没有调用
lock.unlock()或发生异常导致锁提前释放
tryLock(long waitTime, long leaseTime, ...) 为什么不会续期?
当你用 tryLock(3, 10, TimeUnit.SECONDS) 这类带 leaseTime 参数的方法时,Redisson 会直接把锁的 TTL 设为 10 秒,且完全禁用 WatchDog。这意味着:哪怕业务逻辑只执行了 2 秒,锁也将在第 10 秒末硬性过期,不管线程是否还在运行。
这种设计是明确的语义选择:你指定了租约时间,就表示“我清楚自己最多需要这么久”,Redisson 不会擅自延长。所以如果你的业务耗时波动大,又想靠续期兜底,就别用带 leaseTime 的 tryLock,改用无参 lock() + 超时控制逻辑。
WatchDog 续期失败的典型表现和原因
最常遇到的现象是:日志里反复出现 org.redisson.RedissonLock#expireEntry 报错,或业务刚跑一半锁突然消失,引发重复执行。这通常指向:
- Redis 连接不稳定,WatchDog 发送
EVAL续期脚本超时或失败 - 线程被意外中断(比如
Thread.interrupt()),WatchDog 检测到后主动放弃续期 - 锁被其他线程调用
unlock()—— 即使不是加锁线程,只要能删 key 就会清掉 WatchDog 关联的内部定时任务 - 应用启用了 Spring 的异步上下文(如
@Async),但锁对象没正确传递到新线程,导致原线程退出后 WatchDog 失效
生产环境必须检查的三个配置点
WatchDog 是否可靠,不只取决于代码写法,更依赖基础配置:
-
spring.redisson.lock.watchdog.timeout(实际不存在,这是个常见误解)—— Redisson 没有这个配置项;续期间隔固定为internalLockLeaseTime / 3,而internalLockLeaseTime默认 30 秒,所以续期周期是 10 秒。要调整,只能改Config.lockWatchdogTimeout(单位毫秒),但一般不建议动 - 确保
Config.useSingleServer().setConnectionPoolSize(...)足够大(至少 64),否则 WatchDog 线程可能抢不到连接资源 - 禁用
Config.setEventLoopGroup(...)自定义 EventLoop(除非你非常清楚 Netty 线程模型),否则可能导致 WatchDog 定时器注册失败
真正容易被忽略的是:WatchDog 只守护“当前 JVM 进程内”的锁状态。一旦服务重启、Pod 重建或机器宕机,WatchDog 进程消失,锁会在 TTL 到期后自动释放——这反而是安全设计,不是缺陷。











