1. 今天做了什么
- 学习使用成熟的 Redisson 解决自定义 Redis 分布式锁目前存在的问题:
- 不可重入;
- 不可重试;
- 超时释放;
- 主从一致性问题。
- 完成 Redisson 的基本使用:
- 引入依赖;
- 通过配置类进行配置;
- 获取锁对象;
- 尝试获取锁并释放锁。
- 学习 Redisson 可重入锁、锁重试、WatchDog 自动续期和 MultiLock 的实现思路。
2. 核心知识点
Redisson 可重入锁:
- 采用 Hash 存储结构:key 是锁的 key,field 是线程标识,value 是重入次数。
- 获取锁:
- 判断 key 是否存在;
- 不存在则获取锁,并设置有效期;
- 存在则判断线程标识与自己是否一致;
- 一致则将重入次数加 1,并更新过期时间;
- 不一致则说明锁被其他线程持有,获取失败。
- 释放锁:
- 判断 key 是否存在;
- 不存在则说明锁已经释放,结束;
- 存在则判断线程标识是否一致;
- 不一致则说明锁已经释放并被其他线程持有,结束;
- 一致则将重入次数减 1;
- 重入次数为 0 时删除 key;
- 重入次数不为 0,说明本次释放不是最外层,仍有业务逻辑,更新过期时间。
- 获取锁与释放锁均使用 Lua 脚本,以保证原子性。
Redisson 锁重试:
- 执行获取锁的 Lua 脚本;成功返回
null,失败返回锁的剩余过期时间; - 返回
null说明获取成功,流程结束; - 获取失败则进入等待流程;
- 等待流程维护剩余等待时间,一旦小于等于 0,直接结束,不再等待;
- 剩余等待时间大于 0 时,订阅并等待锁释放信号;
- 等待超时则结束,未超时则再次尝试获取锁。
- 执行获取锁的 Lua 脚本;成功返回
Redisson 解决超时释放问题:
- 未设置过期时间时会启动 WatchDog;
- WatchDog 使用自动续约的定时任务,每 10 秒续约一次,避免业务执行期间锁超时;
- 成功释放锁后取消 WatchDog。

- Redisson MultiLock:
- 搭建多个独立的 Redis 节点;
- 所有节点的锁都获取成功,整体获取锁才成功;
- 如果超时或有节点获取失败,则释放已经获取的锁;
- 它用于处理主从一致性问题导致的锁失效:主节点宕机时,如果锁 key 尚未同步,从节点接替主节点会导致 key 丢失,其他线程可能获取锁;
- 多个独立节点要求全部加锁成功,某个节点宕机时,其他线程无法获取完整的锁。
- MultiLock 的缺点:一个节点宕机会导致所有进程都无法获取完整的锁。
3. 深度思考
- 自定义 Redis 分布式锁可以逐步解决互斥、误删和原子性问题,但可重入、重试、自动续期及主从一致性处理更复杂,适合直接采用 Redisson 这类成熟方案。