redisson通过watchdog机制实现自动续期:调用lock()或trylock(-1)时启动,默认30秒租约、每10秒用lua脚本检查并重置过期时间,unlock后立即停止,兼顾防死锁与业务连续性。

Java 中的锁机制在分布式场景下无法直接复用 JUC 的 ReentrantLock,因为其作用域仅限于单 JVM 进程。Redisson 通过封装 Redis 原语,并融合 Java 锁接口语义,实现了跨进程、跨机器的可重入分布式锁,其中自动续期(Watchdog)是其解决业务执行时间不可预估这一核心痛点的关键设计。
Redisson 如何把 Java 锁语义映射到 Redis
Redisson 的 RLock 接口继承自 java.util.concurrent.locks.Lock,保留了 lock()、tryLock()、unlock() 等方法,让开发者能以熟悉的方式编码。但底层不再依赖 AQS,而是:
- 用 Redis Hash 结构存储锁信息:key 是锁名,field 是“客户端ID:线程ID”,value 是重入次数;
- 加锁操作由 Lua 脚本原子执行:检查 key 是否存在 → 若不存在则新建并设过期时间;若已存在且属于当前客户端,则重入计数+1并刷新过期时间;否则返回剩余 TTL;
- 解锁也通过 Lua 脚本校验:只允许持有锁的同一客户端删除或递减,杜绝误删。
Watchdog 自动续期怎么工作
当调用 lock() 或 tryLock(waitTime, -1, unit)(leaseTime 设为 -1)时,Redisson 启动 Watchdog 机制:
- 默认锁初始租约时间为 30 秒(
lockWatchdogTimeout = 30_000ms); - 后台守护线程每 10 秒(即
lockWatchdogTimeout / 3)向 Redis 发送一次续期请求; - 续期动作仍是 Lua 脚本:仅当该锁 key 存在、且 hash 中包含当前客户端标识时,才将过期时间重置为 30 秒;
- 一旦线程显式调用
unlock(),Watchdog 立即停止;若线程崩溃,10 秒内无续期,锁自然过期,其他节点可获取。
为什么不能靠手动设置长过期时间代替 Watchdog
单纯把 leaseTime 设为几小时看似简单,但会带来严重风险:
- 节点宕机后锁长期不释放,资源被“假占用”,系统可用性下降;
- 业务逻辑优化后执行变快,仍要等几小时才释放,吞吐量受限;
- 不同接口耗时差异大,统一设长过期时间难以兼顾安全与效率。
Watchdog 在“防死锁”和“保互斥”之间取得动态平衡:既避免无限期持有,又不让锁在业务中途意外失效。
实际使用中的关键配置与注意事项
不是所有场景都默认启用 Watchdog,需注意参数组合:
-
tryLock(5, 20, TimeUnit.SECONDS):等待最多 5 秒,拿到锁后固定 20 秒过期,不启用 Watchdog; -
tryLock(5, -1, TimeUnit.SECONDS):等待 5 秒,拿到锁后启用 Watchdog,默认 30 秒租约、每 10 秒续; - 可通过
Config.setLockWatchdogTimeout(60_000)全局调整默认租约时间; - Watchdog 只对未指定 leaseTime 或设为 -1 的锁生效,且要求 Redis 连接稳定——若网络分区导致续期失败,锁仍会在原租约到期后释放。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











