概述
org.redisson.api.RLock
是 Redisson 提供的 分布式可重入锁(类似 ReentrantLock
),基于 Redis 实现,常用于 分布式环境 下的 并发控制。
1. RLock 详解
🔹 特点
- 基于 Redis 实现,支持 集群环境。
- 可重入,同一个线程可以多次获取同一把锁,不会被阻塞。
- 支持 WatchDog 机制,避免锁因宕机未手动释放而导致死锁。
- 支持超时自动释放,避免死锁问题。
- 支持公平锁、联锁、红锁等多种高级特性。
🔹 依赖
<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.22.1</version>
</dependency>
🔹 获取 RLock
RedissonClient redissonClient = Redisson.create(); // 需要传入 Redis 配置
RLock lock = redissonClient.getLock("myLock");
2. RLock 常用方法
方法 | 说明 |
---|---|
lock() | 阻塞式加锁(默认 WatchDog 续期) |
lock(long leaseTime, TimeUnit unit) | 加锁 + 设定过期时间,到期自动释放 |
tryLock() | 非阻塞式,如果获取不到锁立即返回 false |
tryLock(long waitTime, long leaseTime, TimeUnit unit) | 尝试获取锁,最长等待 waitTime ,成功后 leaseTime 过期自动释放 |
unlock() | 释放锁 |
isLocked() | 判断锁是否被任意线程占用 |
isHeldByCurrentThread() | 判断当前线程是否持有锁 |
forceUnlock() | 强制释放锁,无论是谁持有锁 |
3. RLock 典型应用场景
✅ 1. 解决分布式环境下的并发问题
多个服务实例(如 A
和 B
)同时访问共享资源时,防止并发冲突。
场景:多个线程同时对某个商品库存进行扣减操作,需要防止超卖。
public void reduceStock() {RLock lock = redissonClient.getLock("product_stock_lock");try {lock.lock(); // 加锁(默认30s自动续期)int stock = getStock();if (stock > 0) {updateStock(stock - 1);}} finally {lock.unlock(); // 释放锁}
}
⚠ 注意:如果 lock.lock()
后方法抛异常,未执行 unlock()
,Redisson 默认使用 WatchDog 机制自动续期,不会发生死锁。
✅ 2. 限制用户重复提交
场景:用户短时间内重复提交订单,导致重复下单。
public String submitOrder(String userId) {RLock lock = redissonClient.getLock("order_lock:" + userId);boolean success = lock.tryLock();if (!success) {return "请勿重复提交";}try {processOrder();return "订单提交成功";} finally {lock.unlock();}
}
✅ 3. 分布式定时任务的幂等控制
场景:多个定时任务实例同时启动,保证同一时间只有一个任务执行。
public void executeTask() {RLock lock = redissonClient.getLock("task_lock");if (!lock.tryLock()) {return; // 其他实例已持有锁,当前实例不执行任务}try {performTask();} finally {lock.unlock();}
}
✅ 4. 秒杀场景:高并发库存扣减
场景:多用户高并发秒杀商品,避免超卖。
public boolean secKill(String productId) {RLock lock = redissonClient.getLock("sec_kill_lock:" + productId);try {if (lock.tryLock(100, 10, TimeUnit.MILLISECONDS)) {int stock = getStock(productId);if (stock > 0) {updateStock(productId, stock - 1);return true;}}} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}return false;
}
🔹 关键点
tryLock(100, 10, TimeUnit.MILLISECONDS)
- 等待最长 100ms 获取锁
- 持有锁 10ms 后自动释放
- 适用于高并发业务,防止 Redis 长时间占用锁资源。
✅ 5. 订单支付超时取消
场景:订单创建 30 分钟未支付,自动取消订单。
public void setOrderExpire(String orderId) {RLock lock = redissonClient.getLock("order_expire_lock:" + orderId);lock.lock(30, TimeUnit.MINUTES); // 30 分钟后自动释放锁
}
4. RLock 可能存在的问题
问题 | 解决方案 |
---|---|
锁未释放(死锁) | 1️⃣ lock.lock(leaseTime, TimeUnit.SECONDS) 设置超时2️⃣ 使用 WatchDog 机制 |
Redis 宕机,锁丢失 | 采用 Redis 主从 + 哨兵,或者使用 Redisson RedLock |
线程异常退出,锁未释放 | 1️⃣ try-finally 释放锁2️⃣ lock.lock(leaseTime, TimeUnit.SECONDS) 设定过期时间 |
多个服务实例并发竞争锁 | 使用 tryLock(waitTime, leaseTime, TimeUnit.SECONDS) |
5. 进阶:Redisson 其他锁
锁类型 | 说明 |
---|---|
RLock | 可重入锁 |
RReadWriteLock | 读写锁,读读共享,写独占 |
RFairLock | 公平锁,先请求的先获得锁 |
RMultiLock | 联锁,多个 RLock 绑定在一起 |
RedLock | 红锁,适用于 Redis 主从集群 |
RSemaphore | 信号量,类似 Java Semaphore |
RCountDownLatch | 分布式 CountDownLatch |
示例:读写锁
RReadWriteLock rwLock = redissonClient.getReadWriteLock("my_rw_lock");
rwLock.readLock().lock();
try {System.out.println("执行读操作...");
} finally {rwLock.readLock().unlock();
}
6. 总结
✅ RLock
是基于 Redis 实现的分布式锁,适用于高并发环境
✅ 支持可重入、超时释放、WatchDog 续期
✅ 适用于库存扣减、订单防重、定时任务、秒杀等场景
✅ 如果需要更高可靠性,可使用 RedLock
🔥 RLock
是分布式系统中控制并发的利器,但一定要合理设计超时机制,避免死锁和性能问题! 🚀