Spring Boot 3.x + Vue3 + Redis + RabbitMQ:从零搭建高并发秒杀商城系统(附完整源码)

Spring Boot 3.x + Vue3 + Redis + RabbitMQ:从零搭建高并发秒杀商城系统(附完整源码)

Spring Boot 3.x + Vue3 + Redis + RabbitMQ:从零搭建高并发秒杀商城系统(附完整源码)

前言

“秒杀”是互联网技术领域皇冠上的明珠。在短短几秒内,数百万流量如海啸般涌入,如何保证系统不崩溃、数据不超卖(库存不出现负数)、用户体验流畅,是对全栈工程师架构能力的终极考验。
传统的 Spring Boot MVC + MySQL 架构在秒杀场景下完全无法支撑。本文将带你基于 Spring Boot 3.xVue 3,深度整合 Redis(做库存预热与超卖控制)和 RabbitMQ(做流量削峰与异步解耦),从零搭建一个生产级的高并发秒杀系统。

源码获取方式: 关注公众号【全栈技术精选】,回复关键词 “Seckill2024” 获取完整前后端代码、SQL 脚本及部署文档。

一、 系统架构设计

1.1 核心技术栈

模块技术选型版本作用
后端Spring Boot3.2+基础框架,拥抱 JDK 17+
缓存Redis7.0+库存预热、原子性扣减、防重复点击
消息队列RabbitMQ3.12+削峰填谷,将同步下单转为异步处理
前端Vue 3 + Element PlusLatest高性能页面,轮询秒杀结果
安全Spring Security + JWTLatest用户认证与接口保护

1.2 整体架构图

通过分层架构,我们将流量挡在数据库之外。

持久层

消费者层

消息队列层

缓存层

接入层

客户端

秒杀请求

1. 原子扣减2. 发送消息3. 软削峰4. 异步写入

海量用户

Vue3 秒杀页面

Spring Boot 3.x 秒杀接口

Redis 集群

Lua 脚本保证原子性

RabbitMQ

下单消费者服务

MySQL 8.0


二、 数据库设计

秒杀系统的核心在于“快”,表结构设计应遵循最小化原则,减少复杂的 JOIN 关联。

2.1 ER 实体关系图

被购买

下单

PRODUCT

bigint

id

PK

string

name

int

stock_count

真实库存

int

seckill_stock

秒杀库存

SECKILL_ORDER

bigint

id

PK

bigint

user_id

FK

bigint

goods_id

FK

string

state

0:无效 1:成功 2:支付

datetime

create_time

USER

bigint

id

PK

string

nickname


三、 核心业务流程

这是整个系统的大脑。当用户点击“秒杀”按钮时,系统不会直接操作数据库,而是先经过 Redis 的“安检”。

3.1 秒杀业务时序图

MySQLRabbitMQRedis秒杀后端Vue3 前端用户MySQLRabbitMQRedis秒杀后端Vue3 前端用户步骤1: Redis 预扣库存步骤2: 异步解耦步骤3: 消费者落库alt[库存不足 或 重复秒杀][扣减成功]点击“立即秒杀”1POST /seckill/do2执行 Lua 脚本扣减3返回结果4提示“手慢了/已购买”5发送下单消息6返回“排队中” (前端轮询)7消费消息8INSERT INTO seckill_order9更新前端轮询状态10


四、 核心代码实现

4.1 Redis Lua 脚本:解决超卖问题

为什么用 Lua?因为 Redis 是单线程的,执行 Lua 脚本期间其他命令必须等待,这保证了“判断库存”和“扣减库存”的原子性,彻底解决超卖问题。
脚本位置:src/main/resources/seckill.lua

local stockKey = KEYS[1]local userKey = ARGV[1]..":".. ARGV[2]-- 用户ID:商品ID-- 1. 判断是否重复购买if redis.call('get', userKey)=='1'thenreturn-1end-- 2. 判断库存local stock =tonumber(redis.call('get', stockKey))if stock ==nilor stock <=0thenreturn0end-- 3. 扣库存 redis.call('decrby', stockKey,1)-- 4. 标记用户已买 redis.call('set', userKey,'1') redis.call('expire', userKey,300)return1

4.2 Spring Boot 后端实现

1. 配置依赖

确保引入 Web, Data Redis, AMQP (RabbitMQ) 依赖。

2. 核心服务类
@ServicepublicclassSeckillService{@AutowiredprivateStringRedisTemplate redisTemplate;@AutowiredprivateRabbitTemplate rabbitTemplate;privateDefaultRedisScript<Long> redisScript;@PostConstructpublicvoidinit(){ redisScript =newDefaultRedisScript<>(); redisScript.setScriptSource(newResourceScriptSource(newClassPathResource("seckill.lua"))); redisScript.setResultType(Long.class);}publicStringdoSeckill(Long userId,Long goodsId){String stockKey ="seckill:stock:"+ goodsId;// 执行 Lua 脚本Long result = redisTemplate.execute( redisScript,Collections.singletonList(stockKey),String.valueOf(userId),String.valueOf(goodsId));if(result ==null)return"系统异常";if(result ==0)return"库存不足";if(result ==-1)return"不能重复购买";// 发送消息到 MQ 队列SeckillMessage message =newSeckillMessage(userId, goodsId); rabbitTemplate.convertAndSend("seckillExchange","seckill.key", message);return"排队中...";// 告诉前端等待,前端轮询查询结果}}

4.3 Vue3 前端轮询实现

用户点击秒杀后,前端收到“排队中”,此时开始轮询后端接口查询订单状态,而不是无限等待。

// src/views/Seckill.vue<script setup>import{ ref }from'vue';import axios from'axios';const isSeckilling =ref(false);const status =ref('立即秒杀');conststartSeckill=async()=>{ isSeckilling.value =true;const res =await axios.post('/api/seckill/do',{goodsId:1});if(res.data.includes('排队中')){ status.value ='正在排队...';startPolling();// 开始轮询}else{ status.value = res.data; isSeckilling.value =false;}};conststartPolling=()=>{const timer =setInterval(async()=>{const checkRes =await axios.get('/api/order/status');if(checkRes.data ==='SUCCESS'){clearInterval(timer); status.value ='秒杀成功!'; isSeckilling.value =false;alert('恭喜抢到商品!');}},1000);// 每秒查询一次};</script>

五、 总结与优化

通过 Spring Boot 3.x + Redis + RabbitMQ 的组合,我们将高并发流量在 Redis 层面拦截,利用 MQ 将瞬时流量平滑推送到数据库,实现了高性能数据一致性的平衡。

后续优化方向:

  1. JVM 级别:使用 Spring Boot 3.x 的 虚拟线程来处理 MQ 消费,进一步提升并发吞吐量。
  2. 前端优化:使用 CDN 加速静态资源,防止首页加载慢导致用户无法点击。
  3. 安全加固:在 Controller 层增加 图形验证码滑块验证,防止机器脚本刷单。
源码获取
关注公众号【全栈技术精选】,回复关键词 “Seckill2024”,获取完整的前后端源码、SQL 脚本及 Lua 文件!

Read more

【C++】优选算法必修篇之双指针实战:有效三角形个数 & 和为s的两个数字

【C++】优选算法必修篇之双指针实战:有效三角形个数 & 和为s的两个数字

【C++】优选算法必修篇之双指针实战:有效三角形个数 & 和为s的两个数字 * 双指针应用场景 * 目录 * 1. 有效三角形个数 * 1.1 题目链接 * 1.2 题目描述 * 1.3 题目示例 * 1.4 算法思路 * 1.5 核心代码 * 1.6 示例测试(总代码) * 2. 和为s的两个数字 * 2.1 题目链接 * 2.2 题目描述 * 2.3 题目示例 * 2.4 算法思路 * 2.5 核心代码 * 2.6 示例测试(总代码) * 总结

By Ne0inhk
备战蓝桥杯----C/C++组 (一)所需C++基础知识(上)

备战蓝桥杯----C/C++组 (一)所需C++基础知识(上)

个人主页: wengqidaifeng ✨永远在路上,永远向前走 个人专栏: 数据结构 C语言 嵌入式小白启动! 重要OJ算法题详解 文章目录 * 前言 * 一. 分析大纲,了解所需 * 1. 大纲显示内容 * 2、组别划分与难度关系 * 3、知识点结构分析(按组别) * 3.1 大学C组:基础入门阶段 * 3.2 大学B组:中级提高阶段 * 3.3 大学A组 / 研究生组:高级挑战阶段 * 4.难度系数说明 * 二. C++基础语法(上):从零开始的编程基石 * 1.前言 * 2.开发环境搭建 - DevC++的安装与使用 * 2.1

By Ne0inhk

const 在 C/C++ 中的全面用法(C/C++ 差异+核心场景+实战示例)

const 在 C/C++ 中的全面用法(C/C++ 差异+核心场景+实战示例) const 是 C/C++ 中的只读修饰符,核心作用是限定变量/对象/函数等不可被修改,既能提升代码可读性、避免意外修改,又能让编译器做更多优化(如常量折叠),还能增强类型安全。C 和 C++ 对 const 的支持有核心差异,C++ 在 C 的基础上做了大幅扩展,使其适配面向对象、模板等特性。下面按「基础通用用法」「C 专属特性」「C++ 增强用法」「核心差异」「实战注意事项」展开,覆盖所有高频场景。 一、基础通用用法(C/C++ 均支持,

By Ne0inhk