news 2026/3/12 5:22:22

秒杀系统架构解密:从 100 TPS 到 10 万 TPS,我是如何做“库存扣减”优化的?(Redis Lua + 消息队列)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
秒杀系统架构解密:从 100 TPS 到 10 万 TPS,我是如何做“库存扣减”优化的?(Redis Lua + 消息队列)

🔥 前言:为什么你的秒杀系统一上线就崩?

场景还原:
某电商平台搞促销,限量 100 台 iPhone 15 Pro Max,售价 9.9 元。
活动开始前,运营还在群里喊:“大家准备好,流量要来了!”
活动开始第 0.1 秒,数据库 CPU 飙升 100%,连接池爆满,整个 App 页面转圈圈,最后报 502。
老板脸色铁青,用户骂声一片。

这是初级开发者最容易遇到的“秒杀惨案”。
秒杀系统的核心难点只有一个:如何在极短时间内,处理远超数据库承受能力的并发请求,且保证库存不扣成负数(超卖)。

今天,我就带大家复盘一个秒杀系统从100 TPS(直连数据库)优化到10 万 TPS(Redis + MQ)的完整架构演进之路。


🧱 第一阶段:青铜时代 —— 悲观锁与数据库死锁

最早期的版本,我们想得很简单:用数据库行锁解决并发问题。

伪代码:

-- 开启事务STARTTRANSACTION;-- 1. 查询库存并加锁 (悲观锁)SELECTstockFROMgoodsWHEREid=1FORUPDATE;-- 2. 判断库存IFstock>0THEN-- 3. 扣减库存UPDATEgoodsSETstock=stock-1WHEREid=1;-- 4. 创建订单INSERTINTOorders...;ENDIF;COMMIT;

结局:TPS ≈ 100
FOR UPDATE下,所有请求变成了串行执行。如果有 1 万人抢购,第 1 个人锁住了这行数据,后面 9999 个人都在排队等待锁释放。
数据库直接成为瓶颈,甚至因为锁等待超时引发雪崩


🥈 第二阶段:白银时代 —— 乐观锁的“重试地狱”

为了去掉悲观锁,我们引入了乐观锁(CAS 思想)。

SQL 改进:

-- 不需要查出来加锁,直接在 Update 时判断条件UPDATEgoodsSETstock=stock-1WHEREid=1ANDstock>0;

结局:TPS ≈ 500
虽然没有了显式的锁等待,但在高并发下,大量请求同时竞争同一行记录的写锁 (InnoDB Row Lock)。
MySQL 依然扛不住几万 QPS 的写入。更糟糕的是,如果库存充裕,大量失败的请求需要由业务层进行重试,导致网络风暴


🥇 第三阶段:黄金时代 —— Redis + Lua 脚本(抗住 10 万并发)

我们要明白一个铁律:高并发秒杀,绝对不能让流量直接打到 MySQL。
库存扣减必须在内存中完成。

Redis 是单线程的,天然无锁且高性能。但我们有两个操作:GET(查库存) 和DECR(扣库存)。
如果在 Java 里分两步调 Redis,会有并发安全问题(超卖)。

解决方案:Redis Lua 脚本
Lua 脚本可以保证多条 Redis 命令的原子性。在 Redis 服务器看来,这个脚本就是一个整体,执行期间不会插入其他命令。

核心 Lua 脚本 (seckill.lua):

-- KEYS[1]: 商品库存Key-- ARGV[1]: 扣减数量localstock=redis.call('get',KEYS[1])if(stockandtonumber(stock)>=tonumber(ARGV[1]))then-- 库存充足,执行扣减redis.call('decrby',KEYS[1],ARGV[1])return1-- 成功elsereturn0-- 失败end

Java 调用代码:

// 使用 StringRedisTemplate 执行 Lua 脚本Longresult=stringRedisTemplate.execute(newDefaultRedisScript<>(scriptText,Long.class),Collections.singletonList("goods:stock:1001"),"1");if(result==1){// 扣减成功,进入下一步(异步下单)}else{thrownewBizException("手慢了,已抢光!");}

结局:TPS 飙升至 10w+
Redis 单机理论 TPS 可达 10w。通过 Lua 脚本,我们把复杂的锁竞争变成了极其高效的内存计数器操作。流量被完美挡在了缓存层。


💎 第四阶段:王者时代 —— 消息队列“削峰填谷”

Redis 扣减成功了,但订单还没生成。
如果此时直接调用 MySQL 去INSERT order,MySQL 还是会挂。
因为 Redis 这一层漏下来的成功请求(假设库存 1 万),在一秒内涌入 MySQL,依然是灾难。

解决方案:MQ 异步解耦

  1. Redis 扣减成功后:不操作数据库,而是向 RocketMQ/Kafka 发送一条“创建订单消息”。
  2. 消费者 (Consumer):按照数据库能承受的速度(例如每秒处理 2000 个),慢慢拉取消息并写入 MySQL。

最终架构图:

异步持久层
削峰填谷层
缓存抗压层
Nginx负载均衡
1. 执行 Lua 脚本
库存不足
库存扣减成功
堆积消息
2. 慢速拉取
3. 写入订单
订单消费者
MySQL 数据库
RocketMQ / Kafka
消息缓冲池
Redis集群
Web服务集群
返回: 已抢光
海量用户请求

🛡️ 常见问题:缓存与数据库不一致怎么办?

问:如果 Redis 扣减成功,但 MQ 发送失败,或者消费者写库失败,怎么办?

这涉及到了分布式事务的最终一致性。

  1. 本地消息表:在 Redis 扣减前,先记录一条“消息发送记录”。
  2. MQ 可靠性投递:使用 RocketMQ 的事务消息。
  3. 库存回滚:如果消费者下单失败(例如用户已超过限购数量),必须发送“回滚消息”,把 Redis 里的库存加回去 (INCRBY)。

📝 总结

从 100 TPS 到 10 万 TPS,秒杀系统的本质就是“层层过滤,漏斗模型”

  1. Nginx/网关层:拦截恶意刷单。
  2. Redis 层:利用 Lua 原子性抗住 99% 的读写流量。
  3. MQ 层:将瞬时流量拉平,保护脆弱的数据库。
  4. 数据库层:只处理最终有效的少量写请求。

没有最牛的架构,只有最适合业务场景的取舍。


博主留言:
想看Redis Lua 脚本的完整文件以及RocketMQ 削峰的具体配置吗?
在评论区回复“秒杀”,我发给你一份《高并发秒杀系统微服务工程源码》,拿去跑个压测试试!

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

探索非线性电液伺服系统的模型预测控制(MPC)之旅

非线性电液伺服系统模型预测控制&#xff08;MPC&#xff09;pdf教程matlab/simulink源程序 s函数编写在控制领域&#xff0c;非线性电液伺服系统一直是个颇具挑战但又充满魅力的存在。今天咱就聊聊基于模型预测控制&#xff08;MPC&#xff09;方法以及对应的 Matlab/Simulink…

作者头像 李华
网站建设 2026/3/11 19:24:58

MATLAB 风力发电系统低电压穿越之串电阻策略探索

MATLAB 风力发电系统低电压穿越—串电阻策略 低电压穿越 双馈风力发电机 本人研究方向电机控制与故障诊断嘿&#xff0c;大家好&#xff01;今天来聊聊我在电机控制与故障诊断研究方向中&#xff0c;关于 MATLAB 风力发电系统低电压穿越的串电阻策略这块有趣的内容。咱们都知道…

作者头像 李华
网站建设 2026/3/7 23:28:44

31、Ubuntu 服务器虚拟化与 KVM 配置指南

Ubuntu 服务器虚拟化与 KVM 配置指南 在当今的系统管理领域,虚拟化技术无疑是最热门的趋势之一。通过虚拟化,你能够在同一硬件上创建多个 Ubuntu 实例,并且为每个虚拟机分配服务器的部分资源。现代服务器拥有强大的处理能力,借助虚拟化技术,你可以充分挖掘硬件的潜力。本…

作者头像 李华
网站建设 2026/3/12 1:12:00

匠魂的熔炼注册

匠魂的熔炼系统 代码概述 这是熔炼系统的主要注册类,负责注册: 所有熔炉相关的方块(加热块、焦黑块、各种功能方块) 熔炼相关的物品(模具、铸件等) 方块实体类型 配方序列化器 GUI容器 创造模式标签页 关键部分分析 1. 合金相关定义位置 合金相关的注册在以下位置: …

作者头像 李华
网站建设 2026/3/5 11:15:06

PRML为何是机器学习的经典书籍中的经典?

PRML&#xff08;Pattern Recognition and Machine Learning&#xff0c;中文名《模式识别与机器学习》&#xff09;被誉为机器学习领域的“圣经”&#xff0c;其经典性体现在内容深度与广度、理论框架的统一性、数学严谨性、结构合理性、实践资源丰富性等多个方面&#xff0c;…

作者头像 李华
网站建设 2026/3/10 4:31:08

教程 31 - 材质系统

上一篇&#xff1a;纹理系统 | 下一篇&#xff1a;几何体系统 | 返回目录 &#x1f4da; 快速导航 &#x1f4cb; 目录 引言学习目标材质系统概念材质数据结构材质配置文件材质系统架构材质加载流程配置文件解析字符串工具扩展渲染器集成使用示例常见问题练习与挑战下一步 &am…

作者头像 李华