高并发秒杀系统的 7 个设计原则(12306 / 淘宝都在用)
2026年6月19日
【30 秒读完 · 核心结论】
秒杀不是"程序 + 服务器"的题,是前端 + 后端 + 数据库 + 运维的协同题。
7 个设计原则:前端拦截 / 动静分离 / 库存预热 / 队列削峰 / 限流防刷 / 熔断降级 / 数据兜底。
核心思路:能挡在前面的,绝不放进来。
高并发秒杀系统的 7 个设计原则(12306 / 淘宝都在用)
一、秒杀为什么难?
秒杀场景的 4 个特征:
- 瞬时高并发:10 万+ 用户在同一秒点击
- 读多写少:库存只有 100 件,请求却有 10 万
- 恶意流量:机器人 / 脚本抢单
- 数据一致性:不能超卖、不能少卖
直接的后果:
- 数据库连接耗尽
- 服务雪崩
- 超卖(卖了 110 件,库存只有 100 件)
- 用户体验差(页面打不开、支付失败)
二、7 个设计原则
原则 1:前端拦截(挡住 80% 请求)
做法:
- 按钮置灰:秒杀开始前按钮不可点击
- 验证码 / 滑块:过滤机器人
- 动态 URL:秒杀开始前 URL 不公开
- 客户端限频:每秒最多点击 1 次
效果:挡住 80% 的无效请求(机器人、误触)。
原则 2:动静分离(页面静态化)
做法:
- 商品详情页完全静态化(HTML 缓存)
- CDN 缓存(不打到源站)
- 只把"秒杀按钮"做成动态
效果:用户浏览不消耗源站资源,只在点击秒杀时才打到应用服务器。
原则 3:库存预热(Redis 化)
做法:
- 秒杀开始前,把库存加载到 Redis
- 秒杀时,Redis 原子操作扣减库存(DECR)
- 扣减成功后再异步写入数据库
关键:Redis DECR 是原子操作,天然防超卖。
原则 4:消息队列削峰
做法:
- 用户秒杀请求先进入 MQ(Kafka / RocketMQ)
- 后端服务按速率消费(每秒处理 1000 单)
- 超出部分排队等待
效果:数据库压力从 10 万 QPS 降到 1000 QPS。
原则 5:限流防刷
做法:
- IP 限流:单 IP 每秒最多 10 次请求
- 用户限流:单用户最多抢 1 件
- 设备指纹:同一设备不能多次抢
- 行为分析:识别机器人特征
工具:Sentinel(阿里开源)/ Guava RateLimiter。
原则 6:熔断降级
做法:
- 系统压力大时,非核心功能直接拒绝
- 如:评论功能关闭、推荐功能简化、地址校验降级
- 只保证"下单链路"畅通
原则:宁可少功能,不可全崩溃。
原则 7:数据兜底
最终一致性:
- Redis 库存扣减成功 → 异步写 MySQL
- MySQL 写入失败 → 定时任务对账补单
- 用户支付超时 → 自动取消订单释放库存
关键:Redis 是性能层,MySQL 是真相层。
三、完整链路图
用户点击秒杀
↓
前端校验(按钮置灰 / 验证码)
↓ 80% 请求被拦
CDN(静态页面缓存)
↓ 命中
Nginx 限流(IP / 用户限频)
↓
应用服务器(Sentinel 限流)
↓
Redis DECR(库存原子扣减)
↓ 扣减成功
MQ 削峰(异步处理订单)
↓
后端服务消费(创建订单 + 写 MySQL)
↓
定时任务对账(Redis vs MySQL 数据一致性)
四、3 个真实案例
案例 1:12306 春运抢票
挑战:单日 PV 数百亿,最高并发 100 万+ QPS
做法:分时段放票 + 验证码 + 余票查询缓存 + 后端排队
案例 2:淘宝双 11 秒杀
挑战:峰值 58.3 万笔/秒(2023)
做法:全链路压测 + 单元化架构 + 异地多活
案例 3:小米手机抢购
挑战:10 万件商品 100 万人抢
做法:预约号 + 抽签制(不是抢,是抽),大大降低并发
五、3 个常见误区
误区 1:堆服务器就能解决
错!秒杀瞬时流量是平时的 100 倍,靠堆服务器成本不可控。必须分层拦截。
误区 2:库存放数据库就安全
错!数据库 SELECT + UPDATE 不是原子操作,高并发下必然超卖。必须用 Redis DECR 或 SELECT FOR UPDATE。
误区 3:秒杀完了就完了
错!秒杀后还要做对账:Redis 和 MySQL 数据是否一致?超卖用户要主动退款。
联系方式:400-025-0992
