SpringBoot + Redisson 实现分布式锁实战(附业务案例)
在实际开发中,经常会遇到多实例同时操作同一份数据的情况,如果没有加锁,很容易造成数据不一致。本文以一个试卷解析业务为例,讲解如何使用 Redisson 分布式锁 保证多实例安全写库。
一、业务背景
在我们的试卷解析系统中,解析结果会先写入 Redis 缓存,然后批量写入数据库。
如果多个节点同时处理同一张卷子,可能会出现以下问题:
数据库被重复覆盖,导致题目解析丢失
错题本写入出现覆盖问题
解决办法:在批量写库前加 分布式锁,保证同一时间只有一个节点处理某张卷子。
二、什么是分布式锁
在单机环境中,我们可以用 synchronized
或 ReentrantLock
来保证线程安全。
在分布式环境中(多台应用同时操作同一份数据),本地锁无法保证安全。
分布式锁的目标:同一份数据,在同一时间只能被一个实例修改。
三、为什么选择 Redisson
Redisson 是基于 Redis 的分布式锁实现,优势:
支持可重入锁,类似 Java 的
ReentrantLock
看门狗机制:自动续租,避免任务超时导致锁被提前释放
提供公平锁、读写锁等多种类型
封装简单易用,减少手动实现 SETNX + EXPIRE 的复杂度
四、Redisson 分布式锁基本使用
1. 添加依赖
<dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.23.5</version>
</dependency>
2. 配置 Redis
spring: redis: host: 127.0.0.1 port: 6379
3. 简单示例
@Autowired
private RedissonClient redissonClient;public void doSomething() {RLock lock = redissonClient.getLock("test:lock");try {// 最多等待5秒获取锁if (lock.tryLock(5, TimeUnit.SECONDS)) {System.out.println("加锁成功,执行任务");Thread.sleep(10000); // 模拟耗时操作}} catch (Exception e) {e.printStackTrace();} finally {if (lock.isHeldByCurrentThread()) {lock.unlock();System.out.println("任务完成,释放锁");}}
}
五、结合业务场景实战
在试卷解析系统中,我们实现了如下方法,将 Redis 缓存的解析结果刷回数据库:
@Transactional(rollbackFor = Exception.class)
public void flushToDatabase(Long correctId) {String lockKey = "correct:lock:" + correctId;RLock lock = redissonClient.getLock(lockKey);boolean locked = false;try {locked = lock.tryLock(5, TimeUnit.SECONDS);if (!locked) {System.out.println("任务正在被处理,跳过 correctId=" + correctId);return;}// 读取 Redis 缓存并更新数据库Map<Object, Object> cacheMap = RedisUtils.getHashEntries("correct:cache:" + correctId);if (cacheMap != null) {updateDatabase(correctId, cacheMap);RedisUtils.del("correct:cache:" + correctId);}} catch (InterruptedException e) {Thread.currentThread().interrupt();} finally {if (locked && lock.isHeldByCurrentThread()) {lock.unlock();}}
}
亮点
看门狗机制:即使
updateDatabase
处理时间超过 30 秒,Redisson 会自动续期锁,防止被其他实例抢占安全释放锁:
isHeldByCurrentThread()
避免误释放他人锁原子性:保证同一
correctId
的刷库操作不会被多个节点同时执行
六、注意事项
tryLock
的参数:waitTime
:最多等待多久获取锁leaseTime
:锁自动释放时间(不传则用看门狗机制)
务必在
finally
里释放锁,并判断isHeldByCurrentThread()
避免使用 Redis
KEYS *
扫描全量缓存,生产环境可用SCAN
或维护一个Set
存放待刷的correctId
七、总结
分布式锁是解决多实例并发问题的利器
Redisson 封装了自动续租机制,大幅降低开发复杂度
在刷库、库存扣减、任务幂等等场景下都非常适用
通过本文案例,你可以在自己的 SpringBoot 项目中安全使用 Redisson 分布式锁,实现多实例安全写库。