1. Redisson 分布式锁的核心机制
Redisson 的分布式锁(RLock
)通过 「看门狗(Watchdog)」 机制解决了锁过期时间和业务执行时间不匹配的问题,具体流程如下:
1.1 加锁与默认过期时间
使用
lock()
或tryLock()
方法获取锁时,默认锁的过期时间为 30 秒。关键代码
javajava 复制代码RLock lock = redisson.getLock("myLock"); lock.lock(); // 默认 30 秒过期,后台启动看门狗
1.2 看门狗的工作原理
- 后台线程续期:Redisson 启动一个后台线程(看门狗),每 10 秒 检查一次锁是否仍被当前线程持有。
- 自动续期:如果锁仍被持有,则重置锁的过期时间回到 30 秒(避免业务未完成时锁过期)。
- 释放锁时停止续期:当调用
unlock()
时,看门狗线程会终止续期操作。
2. 如何避免业务未完成时锁过期?
2.1 正确使用看门狗
必须使用默认的
lock()
方法:若手动指定过期时间(如lock.lock(10, TimeUnit.SECONDS)
),看门狗机制会被禁用,此时需自行确保业务在过期时间内完成。推荐写法
javajava 复制代码RLock lock = redisson.getLock("myLock"); try { lock.lock(); // 启用看门狗 // 执行业务逻辑(时间可能超过 30 秒) } finally { lock.unlock(); // 释放锁并停止看门狗 }
2.2 锁续期流程
加锁成功(默认30秒过期)
↓
启动看门狗线程(每10秒检查一次)
↓
业务执行中...
↓
看门狗检测到锁仍被持有 → 重置过期时间为30秒
↓
业务执行完毕 → 调用 unlock() → 释放锁并终止看门狗
3. 关键设计优势
3.1 避免锁提前释放
- 看门狗通过不断续期,确保只要业务线程存活且未释放锁,锁就不会过期。
- 即使业务执行时间超过 30 秒,锁仍会持续续期,直到业务主动释放。
3.2 防止死锁
默认 30 秒过期兜底:如果持有锁的客户端宕机,看门狗线程终止,锁最终会在 30 秒后自动释放,避免死锁。
与纯设置过期时间的区别
- 单纯设置过期时间(如
SET key value EX 30 NX
)无法处理业务超时问题。 - Redisson 的看门狗在客户端存活时动态续期,兼顾了锁的可靠性和灵活性。
- 单纯设置过期时间(如
4. 其他注意事项
4.1 不要手动指定过期时间
错误用法
javajava 复制代码lock.lock(10, TimeUnit.SECONDS); // 手动指定过期时间,看门狗被禁用
若业务执行超过 10 秒,锁会提前释放,导致并发问题。
4.2 确保释放锁
- 必须将
unlock()
放在finally
块中,防止异常导致锁未释放。 - Redisson 的锁支持可重入性,同一线程可多次加锁,需对应数量的解锁操作。
4.3 结合业务设置合理超时
- 虽然看门狗能续期,但业务逻辑应有超时机制(如数据库查询设置超时时间),避免长时间阻塞。
5. 对比其他方案
方案 | 优点 | 缺点 |
---|---|---|
Redisson 看门狗 | 自动续期,无需业务关心超时问题 | 依赖 Redisson 客户端,需保持客户端存活 |
手动设置过期时间 | 实现简单 | 业务超时可能导致锁失效 |
基于 Lua 脚本的锁 | 原子性操作 | 需自行实现续期逻辑,复杂度高 |
总结
- Redisson 看门狗是分布式锁的“守护线程”,通过定期续期解决了锁过期与业务执行时间不匹配的问题。
- 最佳实践:使用默认的
lock()
方法(启用看门狗),避免手动指定过期时间,并在finally
块中释放锁。