Redis 分布式锁实战:Spring Boot 3 步搞定「超卖 / 重复报名」(毕设答辩加分项)
Redis 分布式锁实战:Spring Boot 3 步搞定「超卖 / 重复报名」(毕设答辩加分项)
技术栈:Spring Boot 2.7 + Redis + Redisson(或原生 SET NX)
场景:活动报名、秒杀、实验室预约、选课——同一资源被多人同时抢
结论:这是本科毕设里「性价比最高」的技术亮点之一——代码少、原理清、演示效果好。
一、为什么这个功能能让答辩老师眼前一亮?
很多毕设都是 CRUD:增删改查走一遍,老师已经看腻了。
但如果你能在答辩时说:
“高并发下,我用 Redis 分布式锁解决了重复报名问题,并通过压测验证了正确性。”
老师立刻会多问你两句——这就是亮点。
而且实现难度可控:
-
不需要微服务、不需要 Kafka;
-
一个 Redis + 几十行 Java 代码就能跑;
-
论文里能写:并发场景、锁原理、测试对比。
二、问题本质:并发下的「超卖」
以活动报名为例:
剩余名额:1
用户 A、B 同时点击「报名」
如果没有锁,两个请求可能同时读到「名额=1」,都判断通过,都写入数据库——超卖。
时间线:
T1 A 读名额=1 ✓
T2 B 读名额=1 ✓
T3 A 扣减,写入成功
T4 B 扣减,写入成功 ← 本该失败
数据库层面可以用 UPDATE ... WHERE stock > 0,但毕设里加一层 Redis 锁:
-
答辩更好讲(分布式、并发);
-
可以演示「加锁前后对比」;
-
论文多一个「关键技术」章节。
三、方案选型:Redisson vs 原生 Redis
| 方案 | 优点 | 缺点 |
|------|------|------|
| SET key NX EX 原生 | 无额外依赖,原理透明 | 需自己处理续期、可重入 |
| Redisson | 开箱即用、看门狗自动续期 | 多一个依赖 |
毕设推荐 Redisson:稳定、代码短、文档多。
四、环境准备
1)引入依赖
<!-- Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- Redisson -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>3.23.5</version>
</dependency>
2)application.yml
spring:
redis:
host: 127.0.0.1
port: 6379
database: 0
redisson:
singleServerConfig:
address: redis://127.0.0.1:6379
五、核心代码(可直接抄进毕设)
1)报名 Service:加锁 + 业务
@Service
@RequiredArgsConstructor
public class ActivitySignupService {
private final ActivityMapper activityMapper;
private final SignupMapper signupMapper;
private final RedissonClient redissonClient;
/**
* 活动报名 —— 分布式锁保护临界区
*/
@Transactional(rollbackFor = Exception.class)
public Result signup(Long activityId, Long userId) {
String lockKey = "lock:activity:signup:" + activityId;
RLock lock = redissonClient.getLock(lockKey);
try {
// 等待最多 3 秒,锁持有最多 10 秒自动释放
boolean locked = lock.tryLock(3, 10, TimeUnit.SECONDS);
if (!locked) {
return Result.fail("系统繁忙,请稍后重试");
}
// ===== 临界区开始:以下逻辑同一时刻只有一个线程执行 =====
// 1. 查活动剩余名额
Activity activity = activityMapper.selectById(activityId);
if (activity == null) {
return Result.fail("活动不存在");
}
if (activity.getRemainQuota() <= 0) {
return Result.fail("名额已满");
}
// 2. 防重复报名
if (signupMapper.existsByActivityAndUser(activityId, userId)) {
return Result.fail("您已报名,请勿重复提交");
}
// 3. 扣减名额 + 写入报名记录
int rows = activityMapper.decreaseQuota(activityId);
if (rows == 0) {
return Result.fail("报名失败,名额已满");
}
signupMapper.insert(new Signup(activityId, userId, LocalDateTime.now()));
// ===== 临界区结束 =====
return Result.ok("报名成功");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return Result.fail("报名被中断");
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
}
2)Mapper:乐观扣减(双保险)
// ActivityMapper.java
@Update("UPDATE activity SET remain_quota = remain_quota - 1 " +
"WHERE id = #{id} AND remain_quota > 0")
int decreaseQuota(@Param("id") Long id);
为什么两层?
-
Redis 锁:减少打到 DB 的并发冲突,答辩好讲;
-
SQL 条件更新:最后一道防线,防止极端情况下超卖。
六、原生 Redis 实现(不用 Redisson 的版本)
想论文里写「手写分布式锁原理」可以用这个:
@Component
@RequiredArgsConstructor
public class RedisLockUtil {
private final StringRedisTemplate redisTemplate;
/**
* SET key value NX EX seconds
* 只有 key 不存在时才设置成功 → 获取锁
*/
public boolean tryLock(String key, String value, long expireSeconds) {
Boolean ok = redisTemplate.opsForValue()
.setIfAbsent(key, value, Duration.ofSeconds(expireSeconds));
return Boolean.TRUE.equals(ok);
}
/**
* 释放锁:先比对 value 再删,防止误删别人的锁
*/
public void unlock(String key, String value) {
String current = redisTemplate.opsForValue().get(key);
if (value.equals(current)) {
redisTemplate.delete(key);
}
}
}
答辩常问:
- Q:锁过期了业务还没跑完怎么办?
A:Redisson 看门狗自动续期;手写版可设合理过期时间 + 业务尽量短。
- Q:Redis 挂了怎么办?
A:降级为数据库乐观锁;毕设场景可说明「本系统面向校园小规模并发,Redis 单点足够」。
七、怎么在答辩里演示「真的有用」?
方法 1:JMeter / Postman 并发测试
-
活动名额设为 10;
-
用 JMeter 开 50 个线程 同时请求报名接口;
-
看数据库:报名记录是否正好 10 条;
-
去掉锁再测一次 → 可能 >10 条,对比截图放 PPT。
方法 2:前端连点
写个简单脚本或浏览器控制台连发 10 次请求,展示「只有 1 次成功,其余提示已报名/名额满」。
论文测试章节模板:
| 用例 | 并发数 | 名额 | 预期 | 实际(加锁) | 实际(无锁) |
|------|--------|------|------|--------------|--------------|
| 重复报名 | 50 | 10 | 成功10 | 成功10 | 成功13(超卖) |
八、和其他毕设场景的快速迁移
| 原场景 | 锁 Key 设计 | 临界区逻辑 |
|--------|-------------|------------|
| 活动报名 | lock:activity:{id} | 查名额 → 扣减 → 写记录 |
| 实验室预约 | lock:lab:{labId}:{timeSlot} | 查冲突 → 写预约 |
| 选课 | lock:course:{courseId} | 查容量 → 选课记录 |
| 秒杀 | lock:seckill:{productId} | 查库存 → 扣库存 → 订单 |
改一个 key + 改业务逻辑,就能套到新题目上。
九、论文里怎么写才显得专业?
关键技术章节结构建议:
-
问题描述:并发场景下的超卖 / 重复提交
-
方案对比: synchronized(单机) vs Redis 分布式锁(多实例)
-
实现原理:SET NX、锁过期、Redisson 看门狗(可配图)
-
核心代码:加锁范围、finally 释放
-
测试验证:并发测试数据对比
别写: 「采用了先进的 Redis 技术提升系统性能」——太空。
要写: 「在活动报名接口引入 Redisson 分布式锁,保证名额扣减与报名记录写入的原子性。」
十、引流区:想要完整 Redis 锁模块 + JMeter 测试脚本?
评论区留言:
Redis分布式锁 + 语言(Java) + 你的场景(报名/预约/选课)
例如:
Redis分布式锁 Java 活动报名
我会发:
-
Redisson 完整配置 + Service 模板
-
JMeter 并发测试步骤截图版
-
论文「并发控制」章节写作模板
-
答辩 5 个高频追问 + 标准答法
十一、最后一句
Redis 分布式锁是毕设里**少数「代码不多、原理清楚、答辩能讲、测试能证」**的技术点。
加一个锁,你的项目就从「管理系统」升级成「考虑过并发问题的系统」。
更多推荐




所有评论(0)