news 2026/5/9 9:24:51

拒绝 CRUD!Spring Boot + Vue3 打造“亿级并发”电商秒杀系统:Redis Lua + RabbitMQ 削峰填谷实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
拒绝 CRUD!Spring Boot + Vue3 打造“亿级并发”电商秒杀系统:Redis Lua + RabbitMQ 削峰填谷实战

💥 前言:数据库不是许愿池

很多新手做秒杀,逻辑是这样的:

  1. 用户点击 -> 2. 查询数据库库存 -> 3. 如果库存 > 0 -> 4. 减库存,生成订单。

在并发只有 10 的时候,没问题。
但在并发 10 万的时候,MySQL 会瞬间死锁、CPU 飙升 100%,整个系统宕机。

要实现“亿级并发”(虽然我们只有一台破电脑,但架构要向那个方向设计),必须遵循一个原则:把数据库当大爷供着,尽量别烦它。


🏗️ 一、 架构设计:漏斗模型

秒杀的本质是**“限流”“异步”**。

流量漏斗图 (Mermaid):

异步削峰

1. 拦截重复请求
2. 读缓存 (10W QPS)
3. 发送秒杀成功消息
4. 匀速消费 (1000 QPS)
5. 最终落地

海量用户 (100W QPS)

Nginx / CDN

Redis (Lua 脚本扣减库存)

RabbitMQ (削峰填谷)

后端消费者

MySQL 数据库


🚀 二、 第一道防线:Redis + Lua 实现原子扣减

Redis 是单线程的,速度极快。但如果我们分两步操作(先 Get 库存,再 Decr 扣减),在高并发下依然会有线程安全问题(超卖)。

这时候,Lua 脚本登场了。它能保证多条 Redis 命令像一条命令一样原子执行

1. 编写 Lua 脚本 (seckill.lua)
放在src/main/resources下:

-- 参数 KEYS[1]: 商品库存 Key-- 参数 ARGV[1]: 购买数量 (通常是 1)localstock=tonumber(redis.call('get',KEYS[1]))-- 如果库存不存在或小于购买数量,返回 -1if(stock==nil)or(stock<tonumber(ARGV[1]))thenreturn-1end-- 扣减库存redis.call('decrby',KEYS[1],tonumber(ARGV[1]))return1-- 成功

2. Spring Boot 调用 Lua

@AutowiredprivateStringRedisTemplateredisTemplate;publicbooleanseckill(StringuserId,StringgoodsId){// 1. 预加载 Lua 脚本DefaultRedisScript<Long>redisScript=newDefaultRedisScript<>();redisScript.setScriptSource(newResourceScriptSource(newClassPathResource("seckill.lua")));redisScript.setResultType(Long.class);// 2. 执行脚本 (原子操作)Longresult=redisTemplate.execute(redisScript,Collections.singletonList("seckill:stock:"+goodsId),"1");// 3. 判断结果if(result!=null&&result==1){// 抢单成功!但这只是在 Redis 里成功了returntrue;}returnfalse;}

这一步,我们挡住了 99% 的流量。只有库存数量的人能通过。


🌊 三、 第二道防线:RabbitMQ 削峰填谷

即使通过了 Redis,如果瞬间有 1 万个“成功”请求同时打向 MySQL 去创建订单,数据库一样会挂。
我们需要一个蓄水池—— RabbitMQ。

1. 生产者:发送消息 (Controller 层)

if(redisService.seckill(userId,goodsId)){// Redis 扣减成功后,不直接操作数据库,而是发个消息SeckillMessagemessage=newSeckillMessage(userId,goodsId);rabbitTemplate.convertAndSend("seckill_exchange","seckill_route",message);returnResult.ok("排队中...");// 立即返回给前端,不让用户等}else{returnResult.error("秒杀结束");}

2. 消费者:慢慢处理 (Service 层)

消费者可以根据数据库的能力,设置Qos(预取数量),例如每次只取 50 条处理,慢慢写入 MySQL。

@RabbitListener(queues="seckill_queue")publicvoidreceive(SeckillMessagemessage){// 1. 再次判断数据库库存 (防止 Redis 和 DB 数据不一致)Goodsgoods=goodsMapper.getGoods(message.getGoodsId());if(goods.getStock()<=0){return;}// 2. 创建订单 & 扣减真实库存// 这一步必须加事务orderService.createOrder(message.getUserId(),message.getGoodsId());}

🎨 四、 前端 Vue3 的配合:把压力留在浏览器

后端再强,也怕前端疯狂F5刷新。前端需要做两件事:

  1. 按钮置灰:点击“立即秒杀”后,按钮立刻 Disable,防止用户连点。
  2. 答题/验证码:在点击前强制用户进行图形验证或算术题,拉长用户请求的时间差。
  3. 轮询结果:因为后端返回的是“排队中”,前端需要每隔 2 秒轮询一次接口,查询订单是否创建成功。
// Vue3 伪代码consthandleSeckill=async()=>{btnDisabled.value=true;// 1. 禁用按钮constres=awaitapi.startSeckill(goodsId);if(res.code===200){// 2. 进入轮询状态startPollingResult();}else{message.error("抢光了!");btnDisabled.value=false;}}

🛡️ 五、 总结与进阶

通过这套架构,我们实现了:

  1. Redis Lua:原子性扣减,防止超卖,抗住高并发读。
  2. RabbitMQ:异步下单,削峰填谷,保护脆弱的 MySQL。
  3. Vue3:前端限流,优化用户体验。

如果真的有“亿级”并发,还需要做什么?

  • 服务降级 (Sentinel):流量实在太大,直接熔断非核心业务。
  • 分库分表:订单表数据量太大,需要 Sharding。
  • CDN 静态资源缓存:把 CSS/JS/图片全部推到边缘节点。

Next Step:
别光看,去你的 IDE 里建两个 Spring Boot 项目(一个发消息,一个收消息),装个 Docker 版的 Redis 和 RabbitMQ,亲自跑通这个流程。面试时,这绝对是你的杀手锏

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/9 8:54:53

字符串逆序.c

#include <stdio.h> #define MAXS 20void f( char *p ); void ReadString( char *s ); /* 由裁判实现&#xff0c;略去不表 */int main() {char s[MAXS];ReadString(s);f(s);printf("%s\n", s);return 0; } void f( char *p ) {char *qp,temp; while(*q!\0){q…

作者头像 李华
网站建设 2026/5/9 8:07:31

C++26反射功能全曝光(颠覆传统元编程的革命性变革)

第一章&#xff1a;C26反射功能概述C26 标准正在积极引入原生反射&#xff08;Reflection&#xff09;支持&#xff0c;旨在通过编译时元编程能力提升代码的可维护性与通用性。反射功能允许程序在编译阶段查询和操作类型、成员变量、函数签名等结构信息&#xff0c;而无需依赖宏…

作者头像 李华
网站建设 2026/5/3 20:13:44

为什么你的C++代码跑不满CPU?,揭秘内核级性能瓶颈的3个根源

第一章&#xff1a;为什么你的C代码跑不满CPU&#xff1f; 在高性能计算场景中&#xff0c;许多开发者发现即使使用了多线程或优化算法&#xff0c;C程序依然无法将CPU利用率拉满。这背后往往涉及多个系统层级的限制因素&#xff0c;从代码逻辑到操作系统调度&#xff0c;再到硬…

作者头像 李华
网站建设 2026/5/6 4:32:16

C++26 constexpr重大升级全解析(编译期性能飞跃的秘密)

第一章&#xff1a;C26 constexpr重大升级概览C26 对 constexpr 的支持进行了里程碑式的增强&#xff0c;显著扩展了编译期计算的能力边界。此次升级使得更多复杂的运行时操作可以在编译期完成&#xff0c;从而提升程序性能并减少运行时开销。更广泛的类型支持 C26 允许在 cons…

作者头像 李华
网站建设 2026/5/8 6:02:32

【C++26内存模型深度解析】:std::execution并发编程的5大核心变革

第一章&#xff1a;C26内存模型演进与std::execution的全局图景C26 标准正在重塑现代并发编程的边界&#xff0c;其核心变革集中在内存模型的精细化控制与执行策略的抽象化。通过引入更灵活的内存顺序语义和统一的执行上下文管理机制&#xff0c;标准为高并发、低延迟系统提供了…

作者头像 李华
网站建设 2026/5/9 3:45:30

【独家披露】AAA游戏团队不会告诉你的C++渲染质量黑科技

第一章&#xff1a;C游戏渲染质量的底层逻辑游戏渲染质量在现代C引擎开发中&#xff0c;依赖于对图形管线、内存布局与计算效率的深度掌控。其底层逻辑不仅涉及GPU指令调度&#xff0c;还包括CPU端的数据组织方式&#xff0c;二者协同决定了最终画面的表现力与性能平衡。渲染管…

作者头像 李华