下面给你一套非常硬核、毕设/面试双杀的方案:

《基于 Java + MySQL + Redis 的高并发秒杀系统实战》

✅ 支持 乐观锁 / 悲观锁 / Redis 预减库存 / 接口限流

✅ 技术深度够,答辩老师基本不会为难你

✅ 可以直接当 毕设 / 课程设计 / 技术博客 / 面试项目


一、业务场景

以「商品秒杀」为例:

  • 商品库存:100 件

  • 瞬时并发:10000+ 请求

  • 核心问题:

    • 超卖(库存 < 0)

    • 重复下单

    • 数据库被打爆

    • 接口被刷


二、技术架构

客户端
   ↓
Nginx(负载均衡)
   ↓
SpringBoot
├── 接口限流(Redis + Lua)
├── 秒杀接口
│   ├── Redis 预减库存
│   └── MQ 异步下单(可选)
├── 库存回滚
↓
MySQL(订单 / 商品)
Redis(缓存 + 计数 + 限流)

技术

作用

SpringBoot

快速开发

Redis

缓存、预减库存、限流

MySQL

持久化

MyBatis

ORM

Redisson / Lua

分布式锁

RabbitMQ(可选)

异步削峰


三、数据库设计(极简但够用)

1️⃣ 商品表 seckill_product

CREATE TABLE seckill_product (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(100),
  stock INT,
  price DECIMAL(10,2),
  start_time DATETIME,
  end_time DATETIME
);

2️⃣ 订单表 seckill_order

CREATE TABLE seckill_order (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  user_id BIGINT,
  product_id BIGINT,
  create_time DATETIME
);

四、核心流程(答辩必画)

用户请求秒杀
   ↓
接口限流(Redis)
   ↓
Redis 预减库存
   ↓
库存 ≤ 0 → 直接拒绝
   ↓
MySQL 乐观锁 / 悲观锁扣库存
   ↓
下单成功

五、四种核心技术方案(⭐重点)


✅ 方案一:悲观锁(MySQL)

SELECT stock FROM seckill_product WHERE id = 1 FOR UPDATE;
@Transactional
public boolean seckill(Long userId, Long productId) {
    Product p = productMapper.selectForUpdate(productId);
    if (p.getStock() <= 0) return false;

    productMapper.decreaseStock(productId);
    orderMapper.insert(userId, productId);
    return true;
}

📌 缺点:串行化,高并发性能差


✅ 方案二:乐观锁(版本号 / 库存字段)

SQL

UPDATE seckill_product
SET stock = stock - 1,
    version = version + 1
WHERE id = #{id}
  AND stock > 0
  AND version = #{oldVersion};

Java

int rows = productMapper.decreaseStockOptimistic(
        productId, oldVersion);
if (rows == 0) {
    throw new RuntimeException("并发冲突,秒杀失败");
}

📌 优点:并发性能更好

📌 老师最爱问:ABA 问题(可答:秒杀场景影响不大)


✅ 方案三:Redis 预减库存(⭐核心)

Long stock = redisTemplate.opsForValue()
        .decrement("stock:" + productId);

if (stock < 0) {
    redisTemplate.opsForValue()
            .increment("stock:" + productId);
    return "秒杀结束";
}

📌 作用:挡住 90% 无效请求,保护数据库


✅ 方案四:接口限流(Redis + Lua)

Lua 脚本(原子性)

local key = KEYS[1]
local limit = tonumber(ARGV[1])
local current = tonumber(redis.call('get', key) or '0')

if current + 1 > limit then
    return 0
end

redis.call('incr', key)
redis.call('expire', key, 1)
return 1

Java 调用

Long result = redisTemplate.execute(
        redisScript,
        Collections.singletonList("seckill:limit:" + userId),
        "1"
);

if (result == 0) {
    return "操作太频繁";
}

📌 作用:防止用户重复刷接口


六、完整秒杀接口(整合版)

@PostMapping("/seckill")
public String seckill(Long userId, Long productId) {

    // 1. 限流
    if (!rateLimiter.tryAcquire(userId)) {
        return "操作频繁";
    }

    // 2. Redis 预减库存
    Long stock = redisTemplate.opsForValue()
            .decrement("stock:" + productId);
    if (stock < 0) {
        return "已售罄";
    }

    // 3. MySQL 乐观锁扣库存
    Product p = productMapper.selectById(productId);
    int rows = productMapper.decreaseStockOptimistic(
            productId, p.getVersion());
    if (rows == 0) {
        redisTemplate.opsForValue()
                .increment("stock:" + productId);
        return "秒杀失败";
    }

    // 4. 下单
    orderMapper.insert(userId, productId);
    return "秒杀成功";
}

七、缓存预热(重要)

@PostConstruct
public void initStock() {
    Product p = productMapper.selectById(1L);
    redisTemplate.opsForValue()
            .set("stock:1", p.getStock());
}

八、系统特色(⭐答辩必讲)

✅ Redis 预减库存,数据库保护

✅ 乐观锁 + 悲观锁对比分析

✅ Redis + Lua 原子限流

✅ 可扩展 MQ 异步下单

✅ 高并发场景真实落地

✅ 技术深度明显高于普通 CRUD 项目


九、性能对比(论文 / 答辩加分)

方案

QPS

是否超卖

无锁

✅ 超卖

悲观锁

乐观锁

Redis + 乐观锁


十、毕设论文结构建议

章节

内容

第1章

绪论

第2章

相关技术

第3章

需求与场景分析

第4章

系统设计

第5章

核心实现(四种方案对比)

第6章

压力测试(JMeter)

第7章

总结


十一、可扩展方向(工作量拉满)

✅ RabbitMQ 异步下单

✅ 分布式锁(Redisson)

✅ 分库分表

✅ 秒杀页面静态化

✅ 恶意请求风控

✅ 微服务化(Sentinel)


十二、我可以继续帮你做的事 ✅

  • ✅ 给你 完整 SpringBoot 秒杀项目

  • ✅ 写 第4 / 第5 / 第6 章论文

  • ✅ 画 架构图 / 时序图

  • ✅ 写 JMeter 压测方案

  • ✅ 准备 答辩老师常问问题

  • ✅ 改成 分布式 / 微服务版

你现在处于:

👉 开题 / 中期 / 快答辩了 / 面试准备?

告诉我,我按你的目标给你“直接能交的内容”。

更多推荐