Redisson的锁重试和WatchDog机制

Redisson 的分布式锁流程图可以看成"获取锁"和"释放锁"两个流程,中间由 WatchDog 续命机制串联起来。下面按图逐步解释

一、获取锁流程(左半部分)

  1. 尝试获取锁
  • Redisson 会用 Lua 脚本在 Redis 中抢锁(SETNX + Hash 结构记录线程标识)。

2.判断 TTL 是否为 null

  • 如果 Redis 返回的 TTL(锁剩余时间)是 null,说明锁当前没有设置过期时间或已经过期,继续判断 leaseTime。

3.分支:leaseTime 是否为 -1

  • leaseTime = -1:表示用户没有指定锁的过期时间。Redisson 会启动 WatchDog 定时任务,自动给锁续命(默认 30 秒,每 30/3=10 秒续一次),直到业务释放锁。
  • leaseTime != -1:用户指定了过期时间(比如 10 秒),Redisson 会直接把 TTL 设置为 10 秒,不开启 WatchDog。

4.判断剩余等待时间是否 > 0

  • 如果 tryLock 传了 waitTime,表示允许等待;Redisson 会订阅一个释放锁的消息(基于 Redis Pub/Sub),进入等待。
  • 如果没有等待时间或者已经超时,就返回 false,表示加锁失败。

二、释放锁流程(右半部分)

  1. 尝试释放锁
  • 调用 unlock() 时,Redisson 同样用 Lua 脚本判断"锁是不是自己加的"。如果不是,记录异常。

2.判断释放是否成功

  • 成功:发送"锁已释放"的消息给其他等待者,并取消 WatchDog。
  • 失败:说明锁已经过期或被别人释放,记录异常日志,流程结束。

三、WatchDog 机制(图中红色块)

  • WatchDog 是 Redisson 的自动续期机制;只有在 leaseTime = -1 时才会启动。
  • 它每隔 internalLockLeaseTime / 3 秒检查锁是否还被当前线程持有,如果还在,就再次设置 TTL(默认 30 秒)。
  • 一旦 unlock() 成功或线程崩溃,WatchDog 会停止,锁不再续期,自然在 TTL 后释放,避免死锁。

四、leaseTime = -1 的含义

  • leaseTime 是 Redisson 的锁持有时间。如果显式传入一个正数(如 10 秒),锁不会自动续命,到期后自动释放。
  • 当 leaseTime = -1(默认值)时:
  1. Redisson 认为业务不知道会执行多久,需要自动续期。
  2. 每次加锁后都会启动 WatchDog,默认 TTL=30 秒。
  3. WatchDog 每 10 秒检查一次,如果业务还没释放锁,就把 TTL 重置为 30 秒。
  4. 一旦 unlock() 或线程挂掉,WatchDog 停止,锁在 30 秒后自然释放。

简单说:

  • leaseTime = -1 → 启动 WatchDog,自动续命,适合执行时间不确定的任务。
  • leaseTime = 固定值 → 不启动 WatchDog,锁在固定时间后自动释放,适合短任务或明确控制时间。

五、整体小结

  • Redisson 获取锁时,会根据 leaseTime 判断是否需要 WatchDog,并支持等待重试。
  • WatchDog 负责给没指定过期时间的锁续命,保证业务执行期间锁不会提前释放。
  • 释放锁时会发送通知、取消 WatchDog,整个流程由 Lua 脚本保证原子性,避免并发问题。

确实挺绕的。你可以先记住两个点,先用再慢慢补细节:

  1. lock.tryLock():抢不到就等一会,抢到了就执行;等太久就返回 false(自己决定是否重试)。
  2. 不传过期时间(默认 leaseTime = -1)时,Redisson 会自动给你"锁续命",确保业务没跑完锁不会过期;自己手动指定时间时就像普通 setnx,到点自动释放。

先把这俩记住,用起来其实就是 lock.tryLock() + unlock(),其余流程是 Redisson 帮你兜底的。用了几次心里就有数了,别一次把所有细节都背下来

相关推荐
流星白龙4 小时前
【Redis】2.Redis重大版本
数据库·redis·junit
流星白龙4 小时前
【Redis】7.Hash表
数据库·redis·哈希算法
流星白龙5 小时前
【Redis】4.基本全局命令
数据库·redis·缓存
流星白龙8 小时前
【Redis】3.Redis安装与命令行客户端
数据库·redis·缓存
Season45012 小时前
Redis命令 (generic即通用命令)
数据库·redis·bootstrap
我不想名字重复13 小时前
redis缓存和数据库数据保持一致
数据库·redis·缓存
流星白龙16 小时前
【Redis】6.计数其他命令
数据库·redis·缓存
流星白龙16 小时前
【Redis】8.List列表
redis
NWU_白杨16 小时前
三种常用的数据存储技术
数据库·redis·mysql·sqlite
我叫黑大帅16 小时前
我为什么单一消费者的场景下,要用 Redis List 当消息队列?
redis·后端·面试