Redisson 是一个基于 Redis 的 Java 分布式框架,提供了丰富的分布式锁功能,包括 可重入锁、公平锁、联锁(MultiLock)、红锁(RedLock) 等。以下是详细说明:
1. Redisson 锁的类型
(1)可重入锁(Reentrant Lock)重点锁!!最经常用的锁!!
-
特点:同一个线程可以重复获取锁(避免死锁),利用hash结构记录线程id和重入次数。
-
默认锁类型:Redisson 的
RLock
默认就是 可重入锁。图1 可重入锁流程图(来源黑马) -
Lock("lock:order:" + userId;){
threadID : 1 (锁里面只能有该线程ID可以进行重入+1-1的操作)
}
hash结构:锁的名字key :: 第一个获取锁的threadID :: 重入次数value;
-
-
示例:
RLock lock = redisson.getLock("myLock"); try { lock.trylock(); // 加锁(可重入) // trylock参数:1.获取锁的最大等待时间、2.锁自动释放时间,3.单位。 // 业务逻辑 } finally { lock.unlock(); // 释放锁 }
(2)公平锁(Fair Lock)
-
特点:按请求顺序分配锁(避免饥饿问题)。
-
实现:基于 Redis 的队列机制。
-
示例:
RLock fairLock = redisson.getFairLock("fairLock"); fairLock.lock(); // 公平加锁
(3)联锁(MultiLock)
-
特点:
-
锁定多个不同的资源,原子性锁定多个资源(如订单+库存+优惠券),保证这些资源的操作要么全部成功,要么全部失败。
-
所有锁必须在同一个 Redis 集群内(不能跨不同集群或独立节点)
-
-
用途:多资源事务场景。
-
示例:
RLock orderLock = redisson.getLock("order:123"); RLock stockLock = redisson.getLock("stock:456"); RLock couponLock = redisson.getLock("coupon:789"); // 联锁:必须同时锁定 order、stock、coupon RLock multiLock = redisson.getMultiLock(orderLock, stockLock, couponLock); multiLock.lock(); // 只有三个锁都成功才算加锁成功。
- 题外话:图1、2来源黑马点评,说Mutilock锁能解决主从一致问题,错误❌ !实际上能解决这个问题的是(4)redLock。
- 什么是主从一致问题:当 Redis 主节点加锁成功后,如果锁数据未同步到从节点,而主节点突然宕机,从节点晋升为新主节点后,锁状态丢失,导致多个客户端同时持有锁,破坏互斥性
举个例子:
- 假设 Redis 采用 一主一从 架构:
- 客户端 A 向 主节点 申请锁
lock:order
,加锁成功。 - 主节点 还未将锁数据同步给 从节点,就突然宕机。
- 从节点 自动晋升为 新主节点,但此时它没有
lock:order
的记录。 - 客户端 B 向 新主节点 申请同一把锁
lock:order
,加锁成功。
结果:客户端 A 和客户端 B 同时持有锁,导致数据竞争或业务错误。


(4)红锁(RedLock)
-
特点:
-
解决主从一致性问题:在 Redis 主从架构中,防止主节点宕机后锁信息丢失(从节点可能未同步锁数据)。
-
基于多节点投票机制:要求多数节点(N/2 + 1)加锁成功才算真正获取锁。
-
-
原理:
-
向多个 独立的 Redis 主节点(非主从关系)发送加锁请求。
-
只有 多数节点(≥ N/2 +1)加锁成功,才算获取锁成功。
-
即使部分节点宕机,锁依然有效。
-
-
缺点:
-
时钟漂移问题:如果 Redis 节点间系统时钟不同步,可能导致锁提前失效。
-
解决方案:使用单调时钟(如
redis.time()
)而非系统时钟。
-
-
性能开销:需向多个节点发起加锁/解锁请求,延迟较高。
-
再次强调说明:这里的是多个独立的redis节点!而不是同一个集群的不同redis节点。
单 Redis 实例/集群的锁
-
传统方式:在单个 Redis 实例或集群中获取一把锁(如
SET lock_key uuid NX EX 30
)。 -
风险:
-
如果 Redis 主节点宕机,且锁数据未同步到从节点,新主节点可能丢失锁信息。
-
集群模式下,锁的键可能分布在不同的分片,无法保证全局一致性。
-
示例问题场景
-
客户端 A 在 Redis 主节点获取锁成功。
-
主节点宕机,从节点升级为新主节点,但锁数据未同步。
-
客户端 B 向新主节点申请同一把锁,错误地获取成功(导致两个客户端同时持有锁)。
RedLock 的解决方案
核心思想
分散风险:在多个完全独立的 Redis 节点(非主从关系)上同时申请锁,只有 多数节点(N/2 + 1) 加锁成功才算真正获取锁。
数学保证:即使部分节点宕机或网络分区,仍能保证锁的安全性。
具体流程
假设部署 5 个独立 Redis 节点(N=5):
-
客户端向所有 5 个节点发送加锁请求(相同的键和随机值)。
-
每个节点独立执行加锁操作(
SET key random_value NX PX 30000
)。 -
客户端统计成功加锁的节点数:
-
≥ 3 个(多数)成功 → 认为加锁成功。
-
< 3 个成功 → 向所有节点发送解锁请求(清理残留锁)。
-
-
锁的有效时间 = 初始 TTL - 加锁耗时(需时钟同步)。
-
示例:
RLock lock1 = redisson1.getLock("order"); RLock lock2 = redisson2.getLock("order"); RLock lock3 = redisson3.getLock("order"); RLock lock4 = redisson4.getLock("order"); RLock lock5 = redisson5.getLock("order"); RLock redLock = redisson.getRedLock(lock1, lock2, lock3, lock4, lock5); redLock.lock(); // 红锁加锁
2. Redisson 锁的默认行为
-
默认锁类型:
redisson.getLock()
返回的是 可重入非公平锁。 -
看门狗机制:默认加锁 30 秒,并通过后台线程自动续期(避免业务未完成锁过期)。
-
非阻塞尝试:可通过
tryLock()
实现非阻塞获取锁:boolean res = lock.tryLock(10, 60, TimeUnit.SECONDS); // 等待10秒,锁60秒 // 如果这里设置了锁的时间,就不会走看门狗机制了,到期释放锁。
3. 锁的特性对比
锁类型 | 是否可重入 | 是否公平 | 适用场景 |
---|---|---|---|
可重入锁(默认) | ✅ 是 | ❌ 否 | 通用分布式锁 |
公平锁 | ✅ 是 | ✅ 是 | 需要按顺序获取锁的场景 |
联锁(MultiLock) | ✅ 是 | ❌ 否 | 多资源原子操作(如分库分表事务) |
红锁(RedLock) | ✅ 是 | ❌ 否 | 高可用性要求(防单点故障) |
4. 关键注意事项
-
锁释放:必须放在
finally
块中,否则可能导致死锁。 -
锁续期:默认通过看门狗线程自动续期(无需手动处理)。
-
红锁争议:RedLock 算法在实际生产中可能存在争议(如时钟漂移问题),建议仅在多数据中心场景使用。
总结
-
默认锁:可重入非公平锁(
RLock
)。 -
高级锁:公平锁、联锁、红锁按需选择。
-
生产建议:
-
普通场景用默认锁即可。
-
高可用场景可测试红锁(但需评估复杂度)。
-
联锁适用于多资源事务。
-
Redisson 的锁实现是生产级分布式系统的首选方案,合理使用能有效解决并发问题!