Redis分布式锁
什么是分布式锁?
分布式锁是一种跨多个独立进程(通常在不同机器上)实现互斥访问的机制。它与传统单机锁(如 synchronized、ReentrantLock)的核心区别在于:
| 对比维度 | 单机锁 | 分布式锁 |
|---|---|---|
| 作用范围 | 单个 JVM 进程内 | 跨多个 JVM/服务器 |
| 实现原理 | 基于内存对象(对象头、AQS) | 基于外部共享存储(Redis、ZK、DB) |
| 典型场景 | 单应用内的线程安全 | 微服务、集群环境下的资源竞争 |
在分布式系统中,传统的 synchronized 或 ReentrantLock 无效,因为:
- 订单号生成、库存扣减等操作可能同时被多台服务器上的不同线程执行
- 每台服务器有独立的 JVM,无法感知彼此的锁状态
典型场景:
- 防止重复下单(同一用户同时提交多个订单)
- 定时任务幂等(集群中只有一个节点执行)
- 库存扣减(防止超卖)
Redisson
Redisson 是一个运行在 Redis 之上的 Java 内存数据网格(In-Memory Data Grid)。它不仅是一个 Redis 客户端,更是一个封装了大量分布式数据结构(尤其是分布式锁)和服务的工具包
代码示例:从手动挡到自动挡
下面是一个整合了 Redisson 的典型代码片段,展示了如何使用分布式锁进行库存扣减:
1. 添加依赖与配置
首先,在 Spring Boot 项目中配置 RedissonClient:
@Configuration
public class RedissonConfig {
@Bean
public RedissonClient redissonClient() {
Config config = new Config();
// 配置单节点地址
config.useSingleServer().setAddress("redis://127.0.0.1:6379");
return Redisson.create(config);
}
}
2. 业务中使用分布式锁
注入 RedissonClient,获取锁并执行逻辑:
@Service
public class OrderService {
@Autowired
private RedissonClient redissonClient;
public void deductStock(Long productId) {
// 关键点:锁的粒度要包含业务标识
String lockKey = "lock:product:" + productId;
RLock lock = redissonClient.getLock(lockKey);
try {
// 1. 尝试加锁(最多等待100秒,获取成功后持有10秒自动释放)
// 注意:如果只想用看门狗(自动续期),可以写成 lock.lock();
boolean isLocked = lock.tryLock(100, 10, TimeUnit.SECONDS);
if (isLocked) {
// 2. 执行核心业务(如查询库存、扣减库存)
System.out.println(Thread.currentThread().getName() + " 获取锁成功,执行业务...");
// 模拟长业务逻辑
Thread.sleep(5000);
// 业务执行完毕
} else {
System.out.println("获取锁失败,稍后重试");
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
// 3. 释放锁(非常重要,必须放在 finally 中)
if (lock.isHeldByCurrentThread()) {
lock.unlock();
System.out.println("锁已释放");
}
}
}
}
总结
分布式锁是单机锁在分布式环境下的替代品,通过共享存储(Redis/ZK/DB)实现跨进程互斥,核心是解决互斥性、防死锁、容错性三大问题。