Spring Boot + Redis 实战分布式锁:从入门到精通

一、为什么需要分布式锁?在单机环境下,我们使用 synchronized 或 ReentrantLock 就能轻松解决并发问题。但当应用部署到多节点时,每个节点都有独立的JVM进程,本地锁只能控制单个进程内的线程,无法协调多个进程之间的竞争。举一个典型的场景:用户秒杀活动。假设有10000个用户同时抢购100件商品,如果部署了3台服务器,没有分布式锁的话,可能会有300个请求同时通过库存校验,导致超卖。分布式锁的核心作用:保证在分布式环境下,只有一个进程能获取到资源的访问权。二、Redis实现分布式锁的原理Redis 之所以能实现分布式锁,主要依赖以下特性:SETNX 命令:SET if Not eXists,只有key不存在时才设置成功过期时间:防止锁永久占用,导致死锁唯一value:标识锁的持有者,支持安全释放最简单的实现public String tryLock(String key, String value, long expireTime) {

Boolean success = redisTemplate.opsForValue()

.setIfAbsent(key, value, expireTime, TimeUnit.SECONDS);

return success ? value : null;

}

public void unlock(String key, String value) {

if (value.equals(redisTemplate.opsForValue().get(key))) {

redisTemplate.delete(key);

}

}但这只是最基础版本,存在两个致命问题:问题一:锁过期但任务未完成比如设置锁过期10秒,但实际业务需要15秒。10秒后锁自动释放,另一个线程获取锁开始执行,导致两个线程同时持有锁。问题二:原子性问题先查询再删除不是原子操作,可能查询时锁还在,删除时锁已经被别人获取了。三、Redisson 实战:企业级分布式锁Redisson 是 Redis 的主流客户端,封装了完善的分布式锁实现,我们来直接看代码。引入依赖

org.redisson

redisson-spring-boot-starter

3.25.0

使用分布式锁@Service

@Slf4j

public class OrderService {

复制代码
@Autowired
private RedissonClient redissonClient;

public void createOrder(String productId, int quantity) {
    String lockKey = "order:lock:" + productId;
    RLock lock = redissonClient.getLock(lockKey);
    
    try {
        // 尝试获取锁,等待10秒,锁定30秒后自动释放
        boolean locked = lock.tryLock(10, 30, TimeUnit.SECONDS);
        
        if (!locked) {
            log.warn("获取锁失败,商品{}正在被处理", productId);
            throw new BusinessException("系统繁忙,请稍后重试");
        }
        
        // 业务逻辑:检查库存、扣减库存、创建订单
        Integer stock = getStockFromDB(productId);
        if (stock < quantity) {
            throw new BusinessException("库存不足");
        }
        updateStock(productId, stock - quantity);
        Order order = new Order();
        order.setProductId(productId);
        order.setQuantity(quantity);
        orderRepository.save(order);
        
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        throw new BusinessException("订单处理被中断");
    } finally {
        if (lock.isHeldByCurrentThread()) {
            lock.unlock();
        }
    }
}

}Redisson 的三大优势Watch Dog 自动续期:默认每10秒检查一次,如果锁还在持有就自动延长30秒可重入:同一线程可多次获取同一把锁公平锁/读写锁:支持更复杂的锁场景四、常见问题与解决方案Q1: Redis 主从切换导致锁丢失?问题:如果Master宕机,Replication未完成,锁就丢了。解决方案:使用 RedLock 算法,同时在N个独立的Redis实例上获取锁。Q2: 如何选择分布式锁的实现?方案优点缺点Redis SETNX性能高,实现简单需要处理过期、续期Redisson功能完善,开箱即用依赖较重ZooKeeper一致性最强性能较低对于大多数场景,Redisson 是最佳选择。五、总结分布式锁是解决分布式环境下资源竞争的核心手段Redis SETNX 是实现分布式锁的基石生产环境推荐使用 Redisson,它解决了锁超时、原子性、可重入等核心问题使用时注意:在 finally 中释放锁,确保锁一定能被释放希望这篇文章能帮你搞定分布式锁面试题和实战项目!如果觉得有用,一键三连是对我最大的支持~

相关推荐
计算机毕设定制辅导-无忧学长2 小时前
《基于微信小程序的居家医疗陪护预约系统设计与实现》
java·spring boot·微信小程序·uniapp·居家医疗陪护预约系统
我不会起名字3227 小时前
Redis 从 0 到 1(三十三):机器断电 Redis 起不来——AOF/RDB 损坏的 4 步抢救流程
redis·数据恢复·aof·rdb·排查
小郎君6589 小时前
注解式脱敏:用 Jackson 的 ContextualSerializer 做字段级策略(一)
spring boot·spring cloud
csdn_aspnet9 小时前
Redis 入门:Windows、Mac安装指南
数据库·windows·redis·缓存·mac
山甫aa10 小时前
锁一篇搞定:乐观锁、悲观锁、CAS、数据库锁与分布式锁【从零开始的 Web 后端学习】
java·数据库·分布式·后端·学习·web
IT规划师10 小时前
Redis 数据类型全解 - HyperLogLog:12 KB 估出亿级 UV(八)
redis·uv·hyperloglog·.net10
jktantan11 小时前
注解式脱敏:用 Jackson 的 ContextualSerializer 做字段级策略(一)
spring boot·后端·算法·spring cloud·系统架构
aiks_yuan1 天前
Token 放 Redis 还是用 JWT:Java 实测验签和查 Redis 耗时,退出登录、改密码踢下线怎么做(jjwt 0.12 + Redis 7.2)
redis
露天赏雪1 天前
第3篇:Sentinel熔断降级实战:大模型接口抖动时的服务兜底方案
java·开发语言·人工智能·spring boot·spring·servlet·sentinel