第7章 秒杀架构
在讲解新场景之前,先来回顾一下前面几个场景的内容:
| 场景 | 解决方案 |
|---|---|
| 读缓存 | 把数据存放在缓存中,减小数据库的读请求压力 |
| 写缓存 | 碰到流量洪峰时,先将数据写入缓存中,再逐步迁移到数据库 |
| 数据收集 | 利用消息队列把缓存中的数据迁移到数据库中 |
这 3 个场景中涉及的架构设计思路,本章场景都会用到。

7.1 业务场景:设计秒杀架构必知必会的那些事
某一次公司策划了一场秒杀活动,该活动提供了 100件 特价商品(价格非常低),供用户于当年 10月10日22点10分0秒 开始秒杀。
- 平台已积累了几千万用户量
- 预计数十万用户对这些特价商品感兴趣
- 特价商品一般会在 1~2秒 内被一抢而光
- 秒杀开启瞬间会出现一个流量峰值
设计目标
以较小的改动来保证秒杀时的流量洪流不会冲垮服务器。
设计原则
| 原则 | 说明 |
|---|---|
| 商品不能超卖 | 库存100件,只能卖出100件 |
| 订单数据不能丢失 | 下单成功的订单必须保存 |
| 服务器和数据库不能崩溃 | 系统稳定运行 |
| 尽量别让机器人抢走商品 | 保护普通用户权益 |
7.2 整体思路
秒杀架构的设计方案就是一个不断过滤请求的过程。
核心目标:尽量在上层处理用户请求,不让其往下层游动。
根据业务流程,需要在每个步骤中将请求拦截在系统上游:

7.2.1 浏览页面如何将请求拦截在上游
曾出现过这样的状况:系统方方面面都考虑到了,但活动一上线,第三方监控系统就显示异常——出口带宽被占满了!
用户参与活动时页面出现严重卡顿,用户抱怨不断。
解决方案:静态资源尽量使用 CDN
什么是 CDN
CDN(内容分发网络)服务商在全国各地都有服务器,服务器中存放着静态资源的缓存。
CDN 收到域名后:
- 寻找一台响应最快的服务器
- 指向这个服务器的 IP
好处:
- 不用花费自己的服务器资源和带宽
- 响应速度快
- 把静态资源的压力拦截在系统分层的外面
动态请求的处理
| 请求类型 | 处理方式 |
|---|---|
| 商品详情、评论等 | 整合成静态页面放入CDN,或放在Redis缓存 |
| 获取服务器时间 | 放在静态资源或负载均衡层 |
| 判断秒杀结束 | 将结束标识放在Cookie中 |
浏览页面的用户行为,需要把请求尽量拦截在 CDN、静态资源或负载均衡侧,如果确实做不到,也要拦截在缓存中。
7.2.2 下单页面如何将请求拦截在上游

用户进入下单页面时,主要有两个操作动作:
1. 进入下单页面
为了防止别人通过爬虫抓取下单页面信息,需要做以下防护:
| 防护措施 | 说明 |
|---|---|
| 页面URL后台动态获取 | 秒杀时间一到,通过另一个请求获取URL |
| 购买按钮设为Disable | 用户点击后禁用,防止不断点击 |
2. 提交订单
秒杀系统架构方案的核心是订单提交,因为这个步骤的逻辑最复杂。
要想尽一切办法在系统各个分层中把不必要的请求过滤掉。
(1) 网关层面过滤请求

如果能在网关层面拦截用户请求,性价比就很高。要是能在这一层过滤 95%以上 的请求,整个系统也将很稳定。
可以做 3 种限制:
| 限制类型 | 说明 |
|---|---|
| 限定用户访问频率 | 每5秒下单一次 |
| 限定IP访问频率 | 避免机器人自动下单 |
| 时间段内拦截一定比例请求 | 使用限流的漏桶或令牌桶算法 |
(2) 后台服务器过滤请求
请求进入后台服务器后,目标是:
- 保证特价商品不超卖
- 保证特价商品订单数据的准确性
需要考虑以下 4 点:
① 商品库存放入 Redis
用户下单前:
1. 使用 decr 操作扣减库存
2. 判断返回值
- 小于0:秒杀失败,用 incr 恢复库存
- 不小于0:秒杀成功,开始创建订单
确保在秒杀期间不做上架或修改库存之类的业务操作,即通过业务流程来保证数据一致性。
② 订单写入缓存中
订单数据先不放入数据库,而是放到缓存中,然后每隔一段时间(比如100毫秒)批量插入一批订单。
用户下单后流程:
- 进入等待页面
- 页面向后台定时轮询订单数据
- 后台先在 Redis 中查询订单数据
- 查不到说明数据已落库,去数据库查询
- 查到后返回给用户,进入付款页面
③ 订单批量落库
定期将订单批量落库,且在订单落库时扣减数据库中的库存。
④ Redis 停止工作怎么办
| 场景 | 应对措施 |
|---|---|
| 读Redis库存失败 | 直接去数据库扣减库存 |
| 写订单到缓存失败 | 直接将订单写入数据库 |
7.2.3 付款页面如何将请求拦截在上游
在付款页面不需要再过滤用户请求了。
要点:如果一个订单未及时付款而被取消,记得把数据库及 Redis 的库存加回去。
7.2.4 整体服务器架构
为了保障秒杀系统的高可用性,整体服务器架构中需要保证所有层级都是高可用的:
| 组件 | 高可用配置 |
|---|---|
| 静态资源服务器 | 负载均衡 |
| 网关 | 负载均衡 |
| 后台服务器 | 负载均衡 |
| 缓存 Redis | 集群模式 |
| 数据库 | 集群模式 |
| MQ | 主从、分片、Failover |
7.3 小结

秒杀系统设计 Checklist
| 层级 | 检查项 |
|---|---|
| CDN层 | 静态资源是否使用CDN |
| 静态资源层 | 动态数据是否可以静态化 |
| 网关层 | 是否配置用户频率限制 |
| 网关层 | 是否配置IP频率限制 |
| 网关层 | 是否配置限流策略 |
| 后台服务 | 库存是否放入Redis |
| 后台服务 | 订单是否先写缓存 |
| 后台服务 | 是否有Redis故障降级方案 |
| 数据层 | 是否配置高可用 |
还需要注意的要点
| 要点 | 相关章节 |
|---|---|
| 假设后台某服务因秒杀崩溃了,如何避免其他服务雪崩? | 第10章 熔断 |
| 网关层的限流 | 第11章 限流 |
| 付款的数据一致性 | 第13章 数据一致性 |
项目效果
这个秒杀项目上线以后,通过观察后台日志、内部监控平台的数据和第三方监控的数据,并用脚本对比库存扣减情况和订单情况,发现一切正常。
普通客户肯定没有专门"薅羊毛"的人操作快。对于普通客户来说,随机决定比单纯比快要更有机会下单成功。所以基本上秒杀架构都会设计限流。