在分布式系统中,解决资源并发访问冲突是核心挑战之一。传统单机的synchronized或ReentrantLock无法跨JVM生效,因此分布式锁成为必备技术。Redisson作为基于Redis的Java客户端,提供了简单且强大的分布式锁实现方案。本文将手把手教你如何使用Redisson实现分布式锁,并深入分析其底层原理。
KEY: "lock:order:1001"
VALUE:
field: "8743c9c0-0795-4907-87fd-6c719a6b4586:1" (客户端ID+线程ID)
value: 1 (重入次数)
Redisson 提供了 “看门狗” 自动续期机制,默认持锁 30 秒。只要持锁的客户端不断地续期,锁将一直有效,直到显式释放。
org.redisson
redisson-spring-boot-starter
3.21.0
# application.ym
spring:
redis:
host: localhost # Redis服务器地址
port: 6379 # Redis服务器端口
password: # Redis服务器密码(如果设置了密码)
database: 0 # Redis数据库索引,默认为0
@Service
@Slf4j
@RequiredArgsConstructor
public class OrderService {
private final RedissonClient redisson;
private static final String LOCK_PREFIX = "lock:order:";
/**
* 创建订单(带分布式锁)
* @param orderId 订单ID
*/
public void createOrder(String orderId) {
final String lockKey = LOCK_PREFIX + orderId;
final RLock lock = redisson.getLock(lockKey);
try {
// 尝试获取锁(等待3秒,锁持有时间20秒)
if (!lock.tryLock(3, 20, TimeUnit.SECONDS)) {
log.warn("[Redisson] 获取订单锁失败,orderId: {}", orderId);
throw new BusinessException(ErrorCode.LOCK_ACQUIRE_FAILED);
}
// 获取锁成功后执行业务逻辑
log.info("[Redisson] 成功获取订单锁,开始处理订单:{}", orderId);
processOrder(orderId);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.error("[Redisson] 订单处理被中断,orderId: {}", orderId, e);
throw new BusinessException(ErrorCode.THREAD_INTERRUPTED);
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
log.info("[Redisson] 已释放订单锁,orderId: {}", orderId);
}
}
}
private void processOrder(String orderId) {
// 模拟业务处理耗时
try {
TimeUnit.MILLISECONDS.sleep(500 + new Random().nextInt(500));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
log.info("订单处理完成:{}", orderId);
}
}
public void processWithFairLock(String resourceId) {
RLock fairLock = redisson.getFairLock("fairLock:" + resourceId);
try {
fairLock.lock(30, TimeUnit.SECONDS); // 公平锁获取
// 业务逻辑...
} finally {
fairLock.unlock();
}
}
public void multiResourceOperation(String res1, String res2) {
RLock lock1 = redisson.getLock("res1:" + res1);
RLock lock2 = redisson.getLock("res2:" + res2);
RedissonMultiLock multiLock = new RedissonMultiLock(lock1, lock2);
try {
if (multiLock.tryLock(5, 30, TimeUnit.SECONDS)) {
// 多个资源原子操作
}
} finally {
multiLock.unlock();
}
}
public void multiResourceOperation(String res1, String res2) {
RLock lock1 = redisson.getLock("res1:" + res1);
RLock lock2 = redisson.getLock("res2:" + res2);
RedissonMultiLock multiLock = new RedissonMultiLock(lock1, lock2);
try {
if (multiLock.tryLock(5, 30, TimeUnit.SECONDS)) {
// 多个资源原子操作
}
} finally {
multiLock.unlock();
}
}
// 推荐格式:lock:业务模块:资源类型:资源ID
String lockKey = "lock:order:payment:" + orderId;
try {
// 尝试获取锁...
} catch (RedisTimeoutException e) {
metricsCollector.recordLockTimeout(); // 监控上报
throw new ServiceException("系统繁忙,请稍后重试");
} catch (Exception e) {
log.error("锁操作异常", e);
throw new ServiceException("系统错误");
}
检查点:
- 是否在finally块中调用unlock()
- 是否出现线程复用导致线程ID变化
- Redis连接是否正常
检查点:
- WatchDog线程是否正常运行
- 是否显式设置了leaseTime
- Redis服务器时间是否同步
优化方向:
- 缩小锁粒度(从全局锁改为资源级锁)
- 使用读写锁分离场景
- 增加Redis分片
通过Redisson实现分布式锁,开发者可以:
✅ 快速集成成熟的分布式锁方案
✅ 避免重复造轮子的风险
✅ 享受自动续期、可重入等高级特性
结语:
如有问题,还望告知。不胜感激!
这篇文章对你有帮助的话,动动你可爱的小手指,点个赞再走吧。非常感谢!