秒杀漏斗模型该如何设计呢
做秒杀系统时,很多人第一反应都是:
- Redis 扛库存
- MQ 削峰
- 限流
- 异步下单
这些都没错,但如果只是零散地堆技术点,最后很容易出现一个问题:
每个点都做了优化,但整个链路还是扛不住。
原因通常不是你少用了某个中间件,而是你没有从系统整体视角去看秒杀。
真实的秒杀系统,核心不是“让所有请求都进来再处理”,而是:
让请求像漏斗一样,一层一层被筛掉,只让真正有机会成交的流量继续往后走。
这就是秒杀漏斗模型。
这篇文章就从工程实践角度,讲清楚:
- 什么是秒杀漏斗模型
- 为什么秒杀一定要按漏斗来设计
- 每一层漏斗分别解决什么问题
- 一套更接近真实生产环境的秒杀链路怎么落地
一、什么是秒杀漏斗模型
所谓秒杀漏斗模型,本质上是:
把秒杀请求从入口到最终成交,设计成一个逐层收口、逐层过滤、逐层削峰的处理过程。
你可以把它理解成一个漏斗:
- 漏斗上层:海量请求涌入
- 漏斗中层:大量无效请求被拦截
- 漏斗下层:只有少量高价值请求真正进入下单、支付、履约流程
也就是说,秒杀系统不是追求:
所有请求都处理成功
而是追求:
在有限资源下,让最有可能成交的那一小部分请求稳定完成。
这是秒杀系统和普通电商系统最大的区别之一。
二、为什么秒杀一定要做成漏斗
先看一个简单事实。
假设你一场秒杀活动:
- 100 万用户同时抢
- 库存只有 1000 件
这意味着:
- 99.9% 的请求从业务结果上注定不会成功
如果你还让这 100 万请求都完整走一遍:
- 登录校验
- 商品查询
- 库存判断
- 下单事务
- 数据库写入
- MQ 投递
那系统一定扛不住。
所以秒杀的关键不是“处理更多请求”,而是:
尽早识别无效流量,并尽早把它挡在更便宜的层。
这就是漏斗思维的核心:
- 越靠前的层,处理成本越低
- 越靠后的层,处理能力越稀缺
- 越早过滤,整体系统越稳
如果没有漏斗模型,常见后果就是:
- Nginx 被打满
- 应用线程耗尽
- Redis 热点 key 被打爆
- 数据库连接池耗尽
- MQ 积压
- 支付和履约链路也被拖垮
三、秒杀漏斗模型的核心思想
秒杀漏斗不是某一个组件,而是一种系统设计方法。
它强调三件事:
1. 越靠前越便宜
最前面的过滤一定要最轻量。
例如:
- CDN 静态化
- 网关限流
- 验证码
- 活动令牌
这些动作比你进入业务服务、访问 Redis、访问数据库都便宜得多。
2. 越靠后越稀缺
真正昂贵的资源包括:
- Redis 热点库存 key
- 下单服务线程池
- MySQL 事务
- MQ 消费能力
- 支付和履约系统处理能力
这些资源不能被无效请求浪费。
3. 每一层都要收口
漏斗不是只在入口限一次流就结束了,而是每层都要继续做过滤。
例如:
- 网关挡一批
- 资格校验挡一批
- 令牌机制挡一批
- 预扣库存挡一批
- 下单幂等再挡一批
- 支付超时再筛掉一批
最后真正完成支付的,才是最终成交用户。
四、秒杀漏斗可以怎么分层
从真实系统角度,一个比较常见的秒杀漏斗大致可以拆成下面几层。
第一层:流量入口层
这一层面对的是最原始、最粗暴的请求洪峰。
主要目标是:
- 拦截机器流量
- 限制异常请求
- 降低源站压力
常见手段:
- CDN 缓存静态页面
- 前端静态化
- 黑白名单
- IP 限流
- 用户维度限流
- 验证码
- 动态路径
为什么这一层很重要?
因为如果连最外层都不拦,后面所有层都会被无效流量拖死。
比如:
- 活动页面、商品详情页尽量走静态资源
- 秒杀按钮请求前先做人机校验
- 同一用户短时间多次点击直接拦截
这一层的目标不是保证业务正确,而是:
先挡住最便宜也最没价值的流量。
第二层:活动资格层
不是所有用户都有资格参与秒杀。
例如:
- 用户未登录
- 用户未实名认证
- 用户不在活动范围
- 用户不属于会员等级
- 用户已经抢过一次
这类请求应该在真正抢库存前就被过滤掉。
常见做法:
- 用户资格预计算
- 活动白名单
- 用户标签缓存
- 抢购资格令牌
很多系统做得不够好的地方在于:
- 用户一点击就去抢库存
这样会让大量根本没资格的人也去竞争库存资源,白白消耗 Redis 和业务线程。
第三层:请求令牌层
这是秒杀里非常实用的一层。
核心思路是:
不是所有请求都能直接进下单逻辑,必须先拿到令牌。
令牌的作用包括:
- 限制进入核心链路的总量
- 做用户级防刷
- 把无效点击挡在更前面
例如:
- 系统按库存量和放大系数发放令牌
- 用户拿到令牌后,才允许尝试秒杀
- 没拿到令牌,直接失败
令牌比真正下单更轻量,因为它可以只依赖:
- Redis
- 内存计数器
- 活动状态缓存
而不需要直接走数据库事务。
这一层的本质是:
先控制进入核心资源区的人数。
第四层:库存校验层
到了这一层,才是真正意义上的资源竞争。
秒杀库存一般不会直接用数据库实时扣减,而是先做缓存层预扣。
常见方案:
- Redis 原子扣减
- Lua 脚本扣库存
- 本地标记售罄
为什么不能一上来打数据库?
因为数据库事务扛不住这么高的并发争抢。
所以典型做法是:
- Redis 里预热库存
- 请求进来先在 Redis 扣减
- 扣减成功才有资格进入异步下单
- 扣减失败直接返回售罄
这一层的目标是:
把大量“抢不到库存”的请求快速终止,不让它们进入下单链路。
第五层:异步排队层
哪怕 Redis 预扣库存成功,也不能直接让所有请求同时打数据库下单。
这时就需要异步排队。
常见做法:
- Kafka
- RocketMQ
- 本地队列加持久化兜底
流程一般是:
- 用户抢到库存资格
- 系统把下单请求写入 MQ
- 用户收到“排队中”
- 消费者异步创建订单
这样做的好处是:
- 削峰填谷
- 避免数据库瞬时被压垮
- 下单服务可以按自身能力消费
这一层是漏斗里非常关键的一层,因为它把“瞬时洪峰”转成了“可控吞吐”。
第六层:订单创建层
到了这里,请求已经是“比较有希望成交”的流量了。
但即便如此,依然不能放松。
订单创建层通常还要继续做这些事情:
- 幂等校验
- 一人一单校验
- 活动时间校验
- 库存最终确认
- 订单落库
为什么前面已经扣了库存,这里还要校验?
因为前面的库存扣减通常是缓存预扣,而最终业务成功还是要在数据库里落真实订单。
这里经常会配合:
- 唯一索引控制一人一单
- 本地事务保证订单写入
- 消息表或事务消息保证后续一致性
这一层的目标是:
把“拿到资格的人”变成“真正成功的订单”。
第七层:支付转化层
很多人讲秒杀到订单创建就结束了,但真实业务里,秒杀最终是否成功,往往还要看支付。
因为会有大量用户:
- 抢到了
- 下单了
- 但没付款
所以从业务结果上看,真正的秒杀漏斗底部,往往是“完成支付的人数”,而不是“创建订单的人数”。
这一层要处理的事情包括:
- 支付时限控制
- 订单超时关闭
- 支付成功回调
- 释放未支付库存
也就是说,秒杀库存并不是订单创建那一刻就万事大吉,很多系统还会结合:
- 预占库存
- 订单超时回补库存
- 支付成功后最终锁定库存
这一层本质上是在做:
从抢购成功到最终成交的转化管理。
第八层:履约与结果反馈层
秒杀不是下完单就结束。
后面还包括:
- 发货
- 券核销
- 库存最终出库
- 用户结果通知
同时,用户侧还要快速知道结果:
- 秒杀成功
- 排队中
- 已售罄
- 下单成功待支付
- 支付成功
所以这一层通常要做:
- 结果异步通知
- 订单状态查询缓存
- 用户维度结果聚合
它的作用是:
让前面复杂的异步漏斗,对用户表现成一个清晰、稳定、可查询的结果。
五、为什么说漏斗模型的关键是“越早过滤越好”
这个观点非常重要。
秒杀系统里每往后走一步,成本都会明显上升。
大致可以这么理解:
- 网关限流:成本最低
- 活动资格校验:很低
- Redis 令牌:低
- Redis 扣库存:中
- MQ 排队:中
- MySQL 下单事务:高
- 支付、履约、通知:更高
所以如果一个请求注定失败,你应该尽量让它死在前面:
- 没资格,别进库存层
- 没令牌,别进下单层
- 没库存,别进 MQ
- 没支付,别占用履约资源
如果过滤做得晚,后面昂贵资源就会被大量浪费。
这也是为什么秒杀系统的设计重点不是“后端足够强”,而是:
让后端只服务真正值得服务的请求。
六、漏斗模型下的几个核心技术手段
下面把秒杀系统里常见技术点,放回漏斗模型里看,就会更清楚。
1. 限流
位置:
- 网关层
- 用户层
- 接口层
作用:
- 防止系统被瞬时流量打穿
2. 验证码和动态路径
位置:
- 活动入口层
作用:
- 拦截脚本和机器流量
3. 令牌机制
位置:
- 资格层之后、库存层之前
作用:
- 控制进入核心链路的人数
4. Redis 预扣库存
位置:
- 核心资源竞争层
作用:
- 快速判定是否还有抢购机会
5. MQ 异步下单
位置:
- 库存成功之后
作用:
- 削峰填谷
- 把同步压力变成异步可控吞吐
6. 幂等和唯一约束
位置:
- 下单层
- 支付层
作用:
- 防止重复请求、重复下单、重复支付处理
7. 支付超时释放
位置:
- 支付转化层
作用:
- 回收未付款订单占用的资源
七、一个真实的秒杀漏斗链路
如果把整条链路串起来,可以理解成这样:
- 用户访问秒杀页,页面静态化,CDN 抗住大部分流量
- 用户点击抢购,先经过验证码、限流、动态路径校验
- 校验用户活动资格,没有资格直接失败
- 用户尝试获取秒杀令牌,没有令牌直接失败
- 令牌通过后,去 Redis 做库存预扣
- 预扣成功后写入 MQ,返回“排队中”
- 消费者异步创建订单,做幂等和一人一单校验
- 订单创建成功后进入待支付状态
- 用户支付成功后订单最终成交
- 未支付订单在超时时间后关闭,并回补库存
你会发现,这其实就是一个典型漏斗:
- 上层进来的人很多
- 中间被一层层筛掉
- 最后只有极少数人到达底部成交
八、秒杀漏斗模型的价值,不只是“扛高并发”
很多人理解秒杀漏斗,只看到“削峰限流”,其实它还有几个更重要的价值。
1. 保护核心资源
漏斗的本质是保护:
- Redis 热点 key
- 下单服务
- 数据库
- 支付系统
2. 提高整体成功率
如果系统不分层过滤,真正有机会成功的请求反而会被无效流量拖死。
3. 提高用户体验
用户不一定要求“必须抢到”,但一定要求:
- 系统别崩
- 结果别乱
- 失败也要快
漏斗模型能让失败更早发生、更快返回。
4. 便于容量评估
每一层漏斗都可以单独评估转化率和承载能力。
例如:
- 入口 100 万请求
- 验证码后剩 60 万
- 资格后剩 20 万
- 令牌后剩 2 万
- 库存成功 1000
- 最终支付 800
这样你就能非常清楚地知道:
- 哪一层拦截效果不好
- 哪一层成本过高
- 哪一层是瓶颈
九、最后总结
秒杀系统真正难的地方,从来都不是某一个技术点,而是:
如何让海量请求在有限资源下,有序地被过滤、排队、转化,最终只让极少数有效请求完成成交。
这就是秒杀漏斗模型的意义。
你可以把它记成一句话:
秒杀不是让所有流量都冲进来,而是让流量一层一层被筛选,越往后越值钱。
如果你理解了这个模型,再去看:
- 限流
- 验证码
- 动态路径
- 令牌机制
- Redis 扣库存
- MQ 削峰
- 异步下单
- 支付超时释放
这些技术点就不会是零散知识,而会变成一套完整的系统设计方法。