高并发秒杀系统的 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

官网https://www.wanmi.com