简单的分布式锁 SpringBoot Redisson
基于SpringBoot和Redisson的分布式锁在实际开发中有多个经典应用场景,以下是几个典型的案例实现:
库存扣减防超卖
在电商秒杀场景中,使用Redisson的可重入锁保证库存扣减的原子性,有效防止超卖问题11。实现关键在于获取商品锁后执行库存检查与扣减:
@Autowired
private RedissonClient redissonClient;public boolean reduceStock(Long productId, Integer quantity) {String lockKey = "product:stock:" + productId;RLock lock = redissonClient.getLock(lockKey);try {// 尝试获取锁,最多等待3秒,锁超时时间为10秒if (lock.tryLock(3, 10, TimeUnit.SECONDS)) {Integer stock = (Integer) redisTemplate.opsForValue().get("product:stock:" + productId);if (stock >= quantity) {redisTemplate.opsForValue().set("product:stock:" + productId, stock - quantity);return true;}}} catch (InterruptedException e) {Thread.currentThread().interrupt();} finally {if (lock.isHeldByCurrentThread()) {lock.unlock();}}return false;
}分布式任务调度控制
在集群环境下确保定时任务仅由一个节点执行,避免重复处理:
public void executeScheduledTask() {RLock lock = redissonClient.getLock("scheduled:task:report");if (lock.tryLock()) {try {// 生成日报表逻辑generateDailyReport();} finally {lock.unlock();}}
}
接口幂等性保障
对于支付、订单创建等关键接口,通过分布式锁实现幂等控制8:
public String createOrder(OrderRequest request) {String idempotentKey = "order:create:" + request.getOrderNo();RLock lock = redissonClient.getLock(idempotentKey);try {if (lock.tryLock(2, 30, TimeUnit.SECONDS)) {// 检查是否已处理if (orderService.existsByOrderNo(request.getOrderNo())) {return "订单已存在";}// 创建订单业务逻辑return orderService.createOrder(request);}} catch (InterruptedException e) {Thread.currentThread().interrupt();}return "处理失败";
}热点数据缓存重建
防止缓存击穿,当缓存失效时仅允许一个线程查询数据库并重建缓存11:
public User getUserById(Long userId) {String cacheKey = "user:info:" + userId;User user = (User) redisTemplate.opsForValue().get(cacheKey);if (user == null) {RLock lock = redissonClient.getLock("user:lock:" + userId);try {if (lock.tryLock(5, 10, TimeUnit.SECONDS)) {// 双重检查user = (User) redisTemplate.opsForValue().get(cacheKey);if (user == null) {user = userMapper.selectById(userId);redisTemplate.opsForValue().set(cacheKey, user, 30, TimeUnit.MINUTES);}} catch (InterruptedException e) {Thread.currentThread().interrupt();} finally {if (lock.isHeldByCurrentThread()) {lock.unlock();}}}return user;
}
跨服务资源锁定
使用联锁(MultiLock)协调多个服务的资源操作11:
public boolean updateMultiResources(Long orderId, Long productId) {RLock orderLock = redissonClient.getLock("order:lock:" + orderId);RLock inventoryLock = redissonClient.getLock("inventory:lock:" + productId);RLock multiLock = redissonClient.getMultiLock(orderLock, inventoryLock);try {if (multiLock.tryLock(5, 30, TimeUnit.SECONDS)) {// 同时锁定订单和库存资源orderService.update(orderId);inventoryService.update(productId);return true;}} catch (InterruptedException e) {Thread.currentThread().interrupt();} finally {if (multiLock.isHeldByCurrentThread()) {multiLock.unlock();}}return false;
}
配置与依赖
在pom.xml中添加Redisson依赖:
<dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId> <version>3.23.5</version>
</dependency> application.yml配置:
spring:redis:host: 127.0.0.1port: 6379
- 锁命名:使用业务相关的有意义的锁名称11
- 超时设置:锁超时时间应大于业务执行最长时间11
- 异常处理:确保锁最终被释放,避免死锁11
- 看门狗机制:Redisson自动续期避免业务未完成锁过期11
- 避免嵌套:不在锁内调用其他带锁的方法
