redisson分布式锁实现原理归纳总结
Redisson 分布式锁的实现原理主要依赖于 Redis 的 Hash 数据结构、Lua 脚本、发布订阅机制以及看门狗(Watchdog)机制,以下是核心要点总结:
1. 核心原理
• 互斥性与可重入性:
通过 Redis 的 Hash 数据结构保存锁的持有者(客户端 UUID + 线程 ID)和重入次数,确保同一线程多次加锁可重入。
• 原子性操作:
使用 Lua 脚本执行加锁、解锁逻辑,保证操作的原子性,避免并发问题。
• 锁续期与自动释放:
通过看门狗机制定期(默认 10 秒续期一次)延长锁的过期时间;若客户端崩溃,锁超时后 Redis 自动删除 Key,防止死锁。
• 非公平锁竞争:
锁释放时通过 Pub/Sub 广播通知等待的客户端,唤醒它们重新竞争锁。
2. Redis 数据类型
• Hash 数据结构(核心实现):
非公平锁的锁信息存储在 Hash 中,Key 格式为 锁名称,Field 为 客户端 UUID + 线程 ID,值为 重入次数。示例:
HSET myLock 58ad9f9e-3a31-4e6d-b7cd-d1a0e7b9e20a:1 1
通过 HEXISTS 和 HINCRBY 判断锁状态及更新重入次数。
• Pub/Sub(等待通知):
未获取锁的客户端订阅锁释放的 Channel(如 redisson_lock__channel:{lockName}),锁释放时通过发布消息减少轮询开销。
• String(锁续期 Key):
看门狗机制使用普通的 String 键(如 watchdog:锁名称)存储续期状态或超时时间。
3. 非公平锁流程
加锁逻辑(Lua 脚本):
- 检查 Hash 中锁 Key 是否存在:
• 若不存在,使用 HINCRBY 设置当前线程为持有者,重入次数初始化为 1,并设置过期时间。
• 若存在且属于当前线程,重入次数 +1。
• 若被其他线程持有,返回锁剩余生存时间(TTL)。
- 通过看门狗启动后台线程,定期续期锁(默认 30 秒过期,续期到 30 秒)。
解锁逻辑(Lua 脚本):
- 检查当前线程是否为锁持有者:
• 若是,重入次数 -1。若减至 0,删除 Hash Key 并发布解锁消息。
• 若否,返回 nil(无效操作)。
- 取消看门狗的续期任务。
锁竞争流程:
- 客户端尝试加锁失败后,进入循环等待。
- 通过 Pub/Sub 订阅锁释放事件,避免轮询 Redis。
- 收到通知后立即重试抢锁,而非按顺序排队(非公平性)。
4. 关键机制对比
特性 | 非公平锁(默认) | 公平锁 |
数据结构 | Hash(存储持有者 + 重入次数) | Hash + List(维护等待队列) |
竞争策略 | 锁释放后多客户端直接抢锁 | 按订阅顺序依次获得锁(类似队列) |
性能 | 高吞吐(无顺序开销) | 低延迟(避免饥饿)但吞吐较低 |
5. 总结
• 非公平锁实现:依赖 Hash 存储锁状态,结合 Lua、Pub/Sub 实现高效竞争。
• 可重入性:基于 Hash 的数值增减实现。
• 容错性:通过自动续期和超时删除避免死锁,依赖 Redis 的持久化和高可用(如主从集群)。
通过上述机制,Redisson 分布式锁在保证安全性与性能的同时,提供了灵活的可重入和非公平锁实现。