一、秒杀业务背景与发展现状
1.1 业务诞生背景
秒杀是电商平台核心营销手段,依靠低价稀缺商品短时间聚拢海量用户,实现拉新、促活、提升平台 GMV。传统商城商品售卖流量平缓,用户分散在全天各个时段;但秒杀具备瞬时集中爆发特性,活动开启 1-3 秒内涌入数十万、上百万请求,流量峰值是日常百倍以上。
从架构视角看,普通电商架构面向 “稳态流量” 设计,追求稳定、事务完整、功能丰富;而秒杀是典型的 “脉冲流量” 场景,峰值极高、持续极短、逻辑极简。早期小型商城直接复用普通商品交易链路,共用数据库、缓存、网关,一旦开启秒杀,极易出现数据库卡死、缓存击穿、服务雪崩、页面打不开、大量用户抢购失败投诉等 P0 级线上故障,严重影响平台稳定性与口碑。
这背后的核心矛盾是:稳态架构无法承载脉冲流量冲击。如果为了一年几次的秒杀,长期保有几十倍的服务器资源,成本会高到无法接受;如果不做专项设计,秒杀又会拖垮整个主站业务。这也是秒杀系统必须独立设计的根本原因。
1.2 行业发展前景
从电商到本地生活、数码潮品、直播带货,秒杀已经成为通用标准化营销玩法。中小商家自建简易秒杀模块、头部大厂搭建独立秒杀专属集群,行业对秒杀系统的性能、稳定性、公平性要求持续升级。
技术层面也经历三代迭代,每一代升级都对应着业务规模的增长和痛点的升级:
初代简易版:复用主站架构,仅加 Redis 缓存,无流量隔离,小活动勉强支撑,大促必崩。这个阶段的核心诉求是 “先有能用的秒杀功能”,优先满足业务上线,不追求极致性能。
第二代分层优化版:主从 Redis+MQ 异步下单,做基础限流,但网关仍使用普通 Spring Cloud Gateway,大量请求打到应用层,资源消耗高。这个阶段解决了 “数据库扛不住” 的问题,但应用层和网关依然是瓶颈。
第三代大厂标准架构:OpenResty 前置网关三层流量过滤、多级缓存、库存分片、动态库存调度、三层隔离架构,实现流量漏斗式衰减,百万请求仅千单落库,兼顾性能、公平、高可用。这个阶段追求的是 “极致性价比”,用最少的服务器资源承载最大的秒杀流量。
1.3 架构师思考:如何设计差异化、可长效迭代的秒杀活动
搭建秒杀系统不能只解决 “抢商品” 单一能力,要从运营 + 技术双维度打造独特活动体系,核心是在性能、成本、体验三者之间找平衡:
流量错峰设计新增预约前置链路,用户提前预约获取抢购资格,过滤无效游客;搭配答题、图形验证码、动态令牌分散瞬时流量,把 1 秒洪峰摊开至 30 秒以上,大幅降低峰值压力。 背后的思考是:峰值越高,系统成本越高;把峰值拉平,用可接受的用户体验损失,换几倍的成本下降,性价比极高。
分层商品分级策略爆款稀缺商品(手机、茅台)独立物理集群隔离,普通秒杀商品共用资源池,差异化分配机器、缓存、数据库资源,避免单一热点拖垮全部活动。 架构思维是 “不搞平均主义”:高价值、高流量的商品配更多资源,普通商品共享资源,整体资源利用率最高。
动态弹性资源调度活动前根据预约人数自动扩容秒杀集群、Redis 分片;活动结束自动缩容,平衡性能与服务器成本;引入动态库存分配方案,解决预分配库存不均、部分分片库存闲置问题。 核心是 “资源跟着流量走”,不用长期保有海量机器,按需扩缩,大幅降低活动成本。
公平防刷体系设备指纹、IP 黑白、账号风控、抢购次数四层校验,区分真实用户与脚本刷子,保障普通用户抢购概率,提升活动口碑。 防刷不只是技术问题,更是业务问题:如果秒杀全被外挂抢走,真实用户抢不到,活动就失去了拉新促活的意义,反而会反噬平台口碑。
柔性降级兜底预设多级降级开关:流量超阈值关闭商品推荐、历史订单等非核心功能;缓存故障切换数据库兜底;MQ 堆积开启同步下单应急方案,极端场景保证基础抢购链路可用。 架构设计的底线思维:最坏情况下,核心功能也要能用。不能追求所有功能完美,要保证极端流量下,抢购主链路不瘫痪。
二、秒杀三大核心致命挑战(底层矛盾拆解)
所有秒杀架构优化,本质都是解决以下三类底层瓶颈,每一类都会直接引发系统雪崩。理解了这三个问题的本质,就能明白为什么秒杀架构要这么设计。
2.1 瞬时超大流量冲击
活动开启瞬间百万级 HTTP 请求同时涌入,普通应用 Tomcat 线程池瞬间打满、数据库连接耗尽、Redis 单节点 CPU100%。
核心矛盾:系统硬件处理能力存在固定上限,瞬时洪峰远超平时数十倍,同步处理全部请求会直接卡死整条交易链路。 很多人第一反应是 “加机器”,但加机器解决不了根本问题:
峰值持续时间极短,可能只有几秒钟,为了几秒钟的峰值长期保有几十倍机器,性价比极低;
数据库、缓存的扩展能力远不如应用服务,应用加再多机器,数据库扛不住照样崩;
流量是脉冲式的,机器扩容需要时间,等扩完容,峰值可能已经过去了。
所以秒杀的核心思路从来不是 “硬抗所有流量”,而是 “过滤 + 削峰 + 限流”,只让和库存数量匹配的有效请求落到数据库。
2.2 热点数据击穿(热点 Key 问题)
爆款商品库存、活动信息全部集中在同一个 Redis Key,所有请求并发读写同一个缓存条目,出现缓存热点:Redis 主线程单命令串行执行,CPU 跑满、请求超时,引发缓存穿透,海量请求直接击穿数据库,出现大量慢 SQL。
为什么热点 Key 这么致命?因为 Redis 是单线程模型,再大的集群,同一个 Key 也只会落在一个分片上。哪怕你有 100 个 Redis 节点,只要大家都抢同一个商品,所有压力还是集中在 1 个节点上,其他 99 个节点都帮不上忙。这就是 “热点集中效应”—— 流量再分散,热点数据也会把压力聚到一点。
这也是为什么普通 Redis 集群解决不了秒杀问题,必须针对热点库存做专门的拆分、分片、本地缓存优化。
2.3 刷子恶意流量挤占资源
爬虫脚本、抢购外挂可批量生成账号、循环提交请求,机器请求占比可达 60% 以上,大量无效请求抢占服务器、带宽、缓存资源,真实用户反而抢不到商品,同时额外增加系统负载,极易触发过载宕机。
刷子流量的危害是双重的:
技术层面:无效请求挤占带宽、CPU、连接池,让真实用户请求变慢甚至失败;
业务层面:破坏抢购公平性,真实用户抢不到,活动效果大打折扣,甚至引发客诉。
防刷不是锦上添花,而是秒杀系统的必备能力。而且防刷一定要做在最上层,越早拦截无效流量,后端压力越小。
三、全链路分层设计思路:实现流量平稳、毫秒级响应
3.1 顶层设计核心思想:漏斗式分层拦截
整体链路遵循越早过滤、成本越低原则,请求从用户端到数据库逐层衰减:CDN→OpenResty 接入层→秒杀应用→Redis 缓存→MQ 消息队列→数据库。 前端 / CDN 拦截 90% 静态无效请求;OpenResty 网关拦截 60% 刷单、非法请求;应用层过滤库存不足、无资格用户;最终仅千级有效订单落到数据库,从根源避免数据库被击穿。
这个设计的底层逻辑非常朴素:不同层级处理请求的成本,差着数量级。
CDN 处理静态请求,成本最低,带宽成本远低于服务器;
OpenResty 网关做校验,成本次之,单机扛几十万连接,CPU 占用极低;
Java 应用处理业务逻辑,成本更高,一个请求占一个线程,内存、CPU 开销大;
数据库处理写入,成本最高,连接数、TPS 都有硬上限。
所以能在上层拦的,绝对不放到下层。每多一层过滤,后端压力就小一个数量级。这就是漏斗架构的精髓:宽进窄出,层层筛选,最后落到数据库的,全是有效请求。
3.2 完整请求流转链路
客户端 & CDN 层:秒杀页面全静态化(商品图、活动文案、倒计时静态资源)托管 CDN,用户就近访问,完全不回源后端;前端按钮置灰、本地时间校验,拦截未到活动时间的请求。 这一层拦截的是 “看页面” 的流量,绝大多数用户只是进来看看,根本没到下单那一步,这部分流量全部挡在最外面。
OpenResty 接入网关层:统一入口,实现 IP 限流、验证码校验、设备指纹防刷、库存快速判断,无库存直接返回,不转发下游服务。 这一层拦截的是 “无效、非法、重复” 的请求,刷子、没库存、超频率的请求,全部在这里直接返回,连应用服务都碰不到。
独立秒杀应用集群:与商城主业务物理隔离,处理用户资格、限购校验,调用 Redis 执行库存预扣。 这一层做业务逻辑校验,保证进来的请求都是合法、有资格的,再去操作缓存。
缓存层:Redis 集群承载库存、活动资格、抢购令牌,通过 Lua 脚本实现原子扣减,毫秒返回抢购结果。 这一层是核心的 “库存闸门”,绝大多数请求在这里分出胜负,成功的才继续往下走,失败的直接返回。
MQ 削峰层:库存扣减成功的请求投递消息队列,异步生成订单、扣数据库库存、发放优惠券。 这一层把瞬时的写入压力摊平,不让数据库直面脉冲流量。
数据库持久层:分库分表存储秒杀订单,定时与 Redis 库存对账,防止超卖、少卖。 这一层是最终的数据权威,只处理最终的有效订单,量已经非常小了。
3.3 两大核心目标落地逻辑
流量平稳可控:通过静态 CDN、答题验证码、MQ 异步、库存分片多重错峰,削平瞬时流量尖峰,把脉冲流量转为平缓匀速请求。 核心是 “削峰填谷”,让系统始终工作在承载力范围内,不会被瞬间洪峰冲垮。
请求极速响应:核心抢购逻辑全部下沉至 OpenResty 与 Redis,避免 Java 应用线程阻塞,绝大多数请求毫秒返回,用户无长时间等待。 用户体验很重要:点一下按钮,几十毫秒就出结果,和等好几秒才转圈,体验天差地别。快,本身就是秒杀体验的核心。
四、三层流量隔离方案(业务 / 系统 / 数据,核心架构基石)
隔离是秒杀第一设计原则:秒杀流量绝对不能污染普通商品交易链路,一旦混布,秒杀峰值会拖垮日常下单、支付业务,造成全站故障。分为三层隔离,本质是 “故障域隔离”—— 把故障锁在最小范围内。
4.1 业务隔离(业务流程完全拆分)
普通商品流程:浏览商详→加购→结算→下单,支持购物车、优惠券、积分复杂逻辑; 秒杀业务流程:静态活动页→资格校验→预扣库存→异步下单,砍掉购物车、多优惠叠加等非必要逻辑,两条业务代码、服务完全分离。 运营侧配套独立活动后台,单独配置秒杀库存、抢购规则,不与普通商品共用运营功能。
为什么要做业务隔离?不只是代码分开,更是故障影响范围隔离。普通商品交易是平台的生命线,不能有任何闪失;秒杀是营销活动,就算出问题,也不能影响正常下单。业务流程分开,代码、服务、逻辑各自独立,秒杀链路出 bug,不会蔓延到主交易链路。
4.2 系统隔离(物理资源拆分)
域名 & 接入隔离:秒杀独立二级域名,单独 Nginx/OpenResty 集群,不与主站共用负载均衡。 入口就分开,流量从域名层面就走不同的链路,不会互相挤占带宽和连接。
应用集群隔离:单独部署秒杀 Cart、Order 微服务,K8s 独立命名空间,资源配额、弹性扩容规则独立,峰值自动扩容不抢占主站容器。 CPU、内存物理隔离,秒杀服务把 CPU 跑满,也不会影响主站服务。这是最直接、最彻底的资源隔离方式。
中间件隔离:独立 Redis 集群、独立 RocketMQ Topic,不与商品、会员共用缓存、消息。 中间件是最容易被打垮的环节,如果共用 Redis,秒杀把 Redis 打满,主站商品缓存也会全部失效,引发全站雪崩。
数据库隔离:专属秒杀订单库、库存表,不混在主交易库,避免秒杀写锁阻塞普通订单。 数据库是最脆弱的环节,一旦锁等待扩散,整个库都会变慢。独立库可以把锁竞争限制在秒杀范围内。
4.3 数据隔离(冷热 / 热点数据分开存储)
活动热数据隔离:秒杀库存、预约资格、抢购令牌全部存入独立 Redis,不共用商品缓存。 热点数据单独存放,避免热点流量冲击其他业务的缓存数据。
冷热数据分离:历史秒杀订单定时归档至冷库,当前活动热数据仅保留近 7 天,控制主库数据量。 数据量越大,索引越重,写入查询越慢。把冷数据迁走,主库只留少量热数据,性能才能保持稳定。
热点商品分片隔离:爆款商品库存拆分为多个分片 Key,分散到不同 Redis 节点,解决单 Key 热点 CPU 打满问题。 把一个热点 Key 拆成多个,压力分散到多台机器,从根源解决热点集中问题。
五、网关架构改造:抛弃普通 SpringCloud Gateway,改用 OpenResty 前置网关
5.1 为什么放弃传统微服务网关?
常规 Spring Cloud Gateway 基于 Java 线程模型,高并发下线程池极易耗尽,每一条请求都要经过 Java 上下文、序列化处理,性能损耗大;大量无效刷单请求打到应用层,会消耗 CPU、内存资源。
打个比方:Java 网关就像一个每个客人都要接待的前台,人多了前台就忙不过来;而 OpenResty 像一个自动检票机,几千人同时过来也能快速检票,不合格的直接拦在外面,根本不用进大厅。
OpenResty 基于 Nginx+Lua 协程模型,单机支持数十万并发连接,无重量级线程开销,可在接入最前端直接拦截无效流量,完全不占用后端应用资源,是秒杀场景最优接入层方案。
选型逻辑非常清晰:
内部服务网关,需要复杂的路由、鉴权、协议转换,选 Spring Cloud Gateway,开发灵活、生态完善;
秒杀接入层,目标是高并发、快拦截、低资源消耗,选 OpenResty,性能高一个数量级。
5.2 OpenResty 技术简单介绍
OpenResty 是扩展版 Nginx,内置 LuaJIT 虚拟机,可在 Nginx 请求 11 个生命周期阶段编写 Lua 脚本,在接入层实现业务逻辑,无需转发后端 Java 服务。 核心优势:异步非阻塞协程、百万并发连接、纳秒级请求拦截、低 CPU 占用,支持限流、校验、缓存、路由全部前置处理。
它的性能优势根源在于模型不同:Java 是 “一个请求一个线程”,并发高了线程多了,上下文切换开销很大;而 Nginx+Lua 是事件驱动 + 协程,单进程就能处理几万连接,几乎没有切换开销,内存占用也极低。对于秒杀网关这种 “逻辑简单、并发极高” 的场景,简直是量身定做。
5.3 OpenResty 落地核心改造功能
静态资源加速:秒杀页面 HTML、图片直接在 OpenResty 本地缓存,回源 CDN 兜底。 静态请求直接在网关返回,连后端应用都不用进,性能最快。
多层前置校验
时间校验:未开始 / 已结束活动直接返回提示。 最简单的校验,也最有效,大量掐点刷新的请求直接挡住。
IP / 设备黑名单:拦截外挂、爬虫 IP。 已知的刷子 IP,直接在网关层拉黑,零成本拦截。
验证码 / 答题校验:Lua 调用 Redis 验证答题结果,错误直接拦截。 把验证码校验前置,不用打到应用层,大幅减少后端压力。
接入层限流:基于令牌桶 Lua 脚本,限制单 IP、单用户每秒最大请求次数,拦截重复刷新。 限流是网关的核心职责,在最入口处把流量限制在系统承载力范围内。
Redis 直连预查库存:Lua 脚本直接操作 Redis 判断商品库存,无库存直接返回,不转发下游应用。 这是收益最大的一点:卖完的商品,所有后续请求直接在网关返回 “已售罄”,连应用都不用碰,能挡住 90% 以上的后续无效请求。
请求路由隔离:普通商品流量路由主站集群,秒杀流量单独转发隔离应用。 网关层就把流量分开,保证两条链路互不干扰。
抢购令牌发放:活动开启后发放一次性有效令牌,无令牌直接拒绝下单。 防止跳步请求,必须经过前置页面才能下单,防刷子直接调用下单接口。
六、全链路流量错峰方案(事前 / 事中 / 事后三层削峰)
错峰核心目标:把 1 秒百万脉冲流量,分摊拉长至数十秒,降低系统瞬时压力,分为下单前、下单中、下单后三阶段。错峰的本质是用可接受的延迟,换系统承载力的大幅提升。
6.1 下单前错峰(事前流量缓释)
页面静态 CDN 化商品图片、活动文案、倒计时全部静态资源推送 CDN,用户访问不回源服务,减少源站请求量,前端仅异步拉取库存少量动态数据(如实际库存等随时变动的信息)。 页面浏览是最大的流量,全部放 CDN,源站只处理真正的抢购请求,压力直接降一个数量级。
预约 + 答题 / 验证码分层过滤预约机制:用户提前预约获取抢购资格,过滤无意愿游客,精准预估峰值流量,提前扩容。 预约的价值是双重的:一方面筛选真实用户,降低无效流量;另一方面让平台提前知道大概有多少人来,好准备资源,不会盲目扩容或者准备不足。
答题 / 图形验证码:用户手动输入答案,天然错开点击时间,打散瞬时并发,同时拦截机器脚本(外挂无法自动识别验证码)。 别小看验证码,它能把 1 秒的峰值,拉平到 30 秒,峰值直接降到原来的三十分之一。代价只是用户多花一两秒钟输入,性价比极高。
6.2 下单中错峰(缓存层削峰)
用户提交抢购请求后,不直接操作数据库,全部在 Redis 完成库存原子预扣: 采用 Lua 脚本一次性完成「库存判断 - 扣减 - 生成抢购凭证」,仅库存扣减成功的有效请求放行,失败请求直接返回,90% 无效请求止步缓存层,不穿透到应用、数据库。
配套热点库存分片方案,单个商品总库存拆分为多组分片,并发请求分散至不同 Redis 节点,解决单 Key 热点瓶颈。
这一层错峰,是把 “数据库级别的并发”,提升到 “缓存级别的并发”。Redis 的处理能力是数据库的几十上百倍,绝大多数请求在这里快速出结果,不用等数据库,用户体验好,数据库压力也小。
6.3 下单后错峰(MQ 异步解耦)
库存预扣成功后,不同步生成订单、扣数据库库存,而是将用户、商品、抢购信息投递 RocketMQ 消息队列。 后端消费服务按数据库最大处理能力匀速拉取消息,同步落库、更新真实库存、发放优惠券,把瞬时写压力转化平稳持续写入,彻底避免数据库瞬间大量写请求阻塞。
同时下单后的短信通知、积分发放、消息推送全部异步消费,不阻塞核心抢购链路。
为什么不直接同步写数据库?因为数据库 TPS 有硬上限,瞬时几千个写入请求过来,直接就锁等待、连接耗尽、卡死了。用 MQ 当缓冲,就像水库泄洪,上游洪水再大,下游也按固定流量慢慢放,数据库永远不会被冲垮。
七、秒杀全阶段流量管控体系
7.1 为什么必须做秒杀前流量管控
库存总量有限,百万用户涌入仅千单可成交,绝大多数请求都是无效流量,白白消耗机器资源。 既然最终只能卖出去 1000 件,就没必要让 100 万个请求都走到数据库,前面拦住就好。
瞬时洪峰极易击穿中间件、数据库,引发全站故障。 没有管控的流量是洪水,有管控的流量是渠水,前者会冲垮堤坝,后者能平稳利用。
无管控场景下刷单脚本占大量流量,普通用户抢购概率极低,活动体验差。 流量管控不只是管 “量”,还要管 “质”,把机会留给真实用户。
临时扩容成本极高,提前管控流量可大幅降低硬件投入,提升投入产出比。 技术优化永远比堆机器便宜,用架构设计省下来的服务器成本,都是纯利润。
7.2 事前流量管控方案:预约资格体系
技术选型:Redis + 预约记录表分库分表
Redis:存储用户预约资格、预约人数计数,支撑高并发预约查询。 高频查询走缓存,保证预约高峰期的查询性能。
MySQL:用户预约关系表水平分表,千万预约数据拆分存储,避免单表过大。 持久化数据落库,分表保证数据量大了之后性能不下降。
实现逻辑
活动开放预约,用户提交预约,Redis 记录用户资格。
预约人数达到预设上限,自动关闭预约入口,提前锁定峰值流量规模。 相当于提前给活动设了 “入场人数上限”,不会无限放人进来。
秒杀开启前,仅拥有预约资格用户可提交下单,无资格请求直接拦截。 从源头减少下单请求量。
优缺点
优点:精准预估流量、提前扩容、大幅降低峰值并发、天然防刷; 缺点:增加业务开发复杂度,需要维护预约存储。
选型标准
爆款高热度秒杀必须使用;小型低流量秒杀可简化,仅用验证码替代。 核心判断标准:预计峰值是否超过系统承载力。如果预计流量很大,预约就是必选项;如果只是小活动,验证码就够了。
7.3 事中流量管控三大手段
7.3.1 验证码 / 答题削峰
技术:HappyCaptcha 图形验证码、自定义答题 Lua 校验 原理:人工操作天然存在时间差,打散并发,同时机器脚本难以自动识别,过滤刷单流量; 适用:所有公域开放秒杀活动。
这是成本最低、效果最明显的错峰手段,几乎所有公开秒杀都会用。
7.3.2 OpenResty 接入层限流
技术:Nginx Lua 令牌桶限流 配置维度:单 IP 每秒请求数、单账号每日抢购次数、活动全局 QPS 上限; 优势:最前置拦截,零后端资源消耗,是第一道流量闸门。
网关限流是 “粗粒度” 的,先把整体流量限制在安全范围内,防止突发流量直接打穿。
7.3.3 Sentinel 应用层精细化限流
OpenResty 粗粒度限流后,业务层使用 Sentinel 做接口、用户维度细粒度限流,搭配熔断降级,下游库存、订单服务异常时快速失败,阻断雪崩。
为什么要两层限流?因为网关层做不了太细的业务逻辑,比如 “单个用户一分钟只能点 3 次下单”,网关可以做;但 “单个用户同一个商品只能抢 1 次”,就需要业务层来做。两层配合,既保证性能,又保证精准。
八、高并发库存扣减完整方案(解决超卖、热点两大痛点)
库存扣减是秒杀系统的核心中的核心,所有设计都围绕它展开。
8.1 核心需求
高并发下精准扣减,杜绝库存负数(超卖);分散热点,单商品十万并发不打满 Redis CPU;订单落库与缓存库存最终一致。
这三个需求优先级是:不超卖 > 扛并发 > 数据一致。超卖是严重的线上事故,会让平台亏钱、赔信誉,所以是第一位的;其次是扛得住并发,不然系统直接崩了;最后是数据最终一致,允许短暂延迟,但最后不能错。
8.2 分层库存架构:一级总库存 + 二级分片库存
一级总库存 Redis:记录商品全部总库存,用于活动数据统计、库存回收调度。 相当于总账本,存总数,做调度用。
二级分片 Redis:单个商品库存拆分为 N 个独立分片,并发请求随机路由不同分片,打散热点。 相当于把一个收银台拆成十个,大家分开排队,速度快十倍,解决单 Key 热点问题。
Lua 原子脚本执行分片库存扣减,单脚本完成查询、扣减、幂等校验,杜绝并发超卖。 为什么用 Lua?因为 Redis 单线程执行 Lua 脚本是原子的,查库存和扣库存能一次性完成,不会出现 “查的时候还有,扣的时候没了” 的并发问题。不用分布式锁,性能更高。
8.3 数据库兜底方案
MQ 消费端执行真实库存扣减,SQL 使用update stock set num=num-1 where num>0原子条件更新,利用 MySQL 行锁作为最后一道超卖防线; 定时任务定时对比 Redis 分片库存与数据库库存,出现不一致自动回补库存、生成告警工单。
为什么还要数据库兜底?因为 Redis 可能丢数据、可能出故障,数据库是最终的权威。定时对账就是保证缓存和数据库最终一致,是数据可靠性的最后一道保险。
8.4 动态库存升级方案(解决静态预分配缺陷)
基础静态分片库存存在短板:部分分片库存耗尽、其余分片仍有库存,用户无法下单。比如 10 个分片,2 个卖完了,剩下 8 个还有,但用户请求落到卖完的分片就会提示无货,明明总库存还有,用户却抢不到。
升级动态库存分配服务:
活动初始化分配库存至各二级分片,一级 Redis 保留机动库存。
分片库存低于阈值,自动从一级总库存补充。
分片库存大量剩余,自动回收至一级库存,重新分配至库存紧张分片。
分片 Redis 节点故障,自动回收该分片剩余库存,避免库存丢失无法售卖。
动态调度的核心价值,是提升库存利用率,避免 “有库存卖不出去” 的尴尬。代价是多了一个调度服务,对于库存量大、分片多的爆款商品,这个投入是非常值得的。
九、限购、热点数据、防刷、风控、容灾全配套方案
9.1 限购处理方案
三层限购校验:
OpenResty 层:限制单 IP 当日抢购次数。 最前置,快速拦截高频 IP。
Redis 层:以
userId+productId为唯一键记录用户抢购记录,设置活动过期时间,重复下单直接拦截。 业务层精准判断,保证一个用户只能抢一次。数据库层:订单表建立用户 + 商品唯一联合索引,兜底防止重复生成订单。 最后一道防线,哪怕上面两层都漏了,数据库也会拦住,不会生成重复订单。
为什么要三层?因为越上层越快,越下层越可靠。上层负责性能,下层负责兜底,层层保障,不会因为某一层出问题就限购失效。
9.2 热点数据全套治理
热点数据分读热点和写热点,解法完全不同:
读热点:商品活动页面静态化,活动基础信息本地缓存 + Caffeine 二级缓存,减少 Redis 查询。 读热点的核心解法是 “增加副本”,哪里近就放哪里,本地缓存、多从库、CDN,都是增加副本,分散读压力。
写热点:库存分片拆分、动态库存调度、单机 Redis 限制单商品 QPS。 写热点的核心解法是 “拆分”,把一个热点拆成多个,分散到不同节点。
实时监控热点 Key,爆款商品自动切换独立 Redis 集群物理隔离。 提前发现热点,专门处理,避免热点冲击其他正常业务。
9.3 多层防刷风控体系
接入层防刷:IP 黑名单、高频请求封禁、设备指纹识别外挂。 最外层,拦最明显的刷子。
业务层防刷:验证码、预约资格、单用户限购。 业务规则层面,增加刷子的作弊成本。
实时风控服务:对接用户行为风控,识别批量注册、批量抢购羊毛党,实时拉黑账号。 深度识别,对付专业黑产。
兜底策略:同一设备多次失败请求,临时封禁 5-10 分钟。 异常行为直接限制,避免持续消耗资源。
防刷是一个对抗的过程,没有一劳永逸的方案,多层叠加才能持续有效。单一手段很容易被绕过,多层组合起来,刷子的成本就会高到无利可图。
9.4 容灾与降级兜底(全链路防护)
容灾的核心思维是:任何组件都可能挂,要提前想好挂了怎么办。
缓存容灾:Redis 集群主从切换,分片故障自动回收库存;缓存整体故障,降级直接操作数据库乐观锁下单。 Redis 挂了不能就不能抢了,降级走数据库,虽然性能下降,但核心功能能用。
MQ 容灾:死信队列存储失败订单,定时重试消费;消息堆积触发流量降级,限制入口 QPS。 MQ 堆积了就限流,别把消费者压垮;失败的消息存起来,慢慢重试,不能丢。
服务降级:峰值自动关闭商品推荐、足迹、评价等非核心接口,释放 CPU 资源。 资源不够了,就把不重要的功能关掉,把资源都留给核心抢购链路。
熔断防护:Sentinel 对库存、支付下游服务配置慢调用熔断,下游故障快速返回提示,不阻塞抢购请求。 下游慢了、挂了,就快速失败,别让请求都卡住,拖垮上游。
全链路监控:QPS、库存、消息堆积、CPU 负载实时告警,提前发现瓶颈。 容灾不能等出了问题才发现,要靠监控提前预警,主动处理。
十、秒杀架构持续升级思路与升级理由
架构升级不是为了炫技,而是业务发展到了某个阶段,旧架构扛不住了,才需要升级。每个阶段都有明确的触发点和升级收益。
10.1 第一阶段升级:从主站混布→三层隔离架构
升级原因:秒杀流量污染普通交易,频繁引发全站故障;通过业务、系统、数据三层隔离,故障范围收窄,秒杀宕机不影响商城日常下单。 触发信号:每次秒杀活动,主站都会卡顿、下单变慢,甚至出现支付失败。 升级收益:故障域缩小,秒杀出问题不影响主业务,平台稳定性大幅提升。
10.2 第二阶段升级:替换 Java 网关为 OpenResty 前置网关
升级原因:传统 SpringCloud Gateway 消耗大量应用资源,大量无效刷单请求打到后端;OpenResty 协程模型高性能,接入层直接拦截 60% 无效流量,大幅降低应用 CPU 负载。 触发信号:应用服务器 CPU 很高,但大部分都是在处理无效请求、重复请求,有效请求占比低。 升级收益:服务器成本降低一半以上,接口响应更快,抗并发能力更强。
10.3 第三阶段升级:单 Redis 库存→分片 + 动态库存架构
升级原因:单商品单 Key 引发 Redis CPU 打满、热点击穿;分片打散并发,动态库存解决分片库存分配不均,提升商品承载并发上限 3-10 倍。 触发信号:爆款商品秒杀时,单个 Redis 分片 CPU 跑满,请求超时,其他分片却很空闲。 升级收益:单商品并发承载能力大幅提升,热点商品不再是瓶颈。
10.4 第四阶段升级:简单同步下单→MQ 异步削峰
升级原因:同步下单大量写请求压垮数据库,锁竞争严重;异步将脉冲流量平滑处理,数据库压力降低 90%,大幅提升系统稳定。 触发信号:秒杀时数据库 CPU 打满,出现大量锁等待,下单超时。 升级收益:数据库写入压力大幅下降,系统稳定性质的飞跃,能承载的有效订单数翻倍。
10.5 第五阶段升级:基础限流→全链路分层流量管控(预约 + 验证码 + 多级限流)
升级原因:无前置流量管控时峰值不可控,机器扩容成本高昂;事前预约 + 事中错峰天然削峰,硬件投入减半,同时优化普通用户抢购公平性。 触发信号:每次活动峰值都不可控,要么准备多了浪费机器,要么准备少了系统崩。 升级收益:流量可预估、可管控,服务器成本下降,用户体验更公平。
10.6 第六阶段升级:配套风控容灾体系
升级原因:无防刷机制活动被外挂占领,用户体验差;无降级容灾极端场景直接宕机;增加风控、熔断、多级降级,实现故障自愈、活动公平。 触发信号:大量用户反馈抢不到,外挂横行;偶尔出现极端流量导致服务宕机。 升级收益:活动公平性提升,系统可用性提升,极端场景也能平稳运行。
十一、全文总结
秒杀系统设计的底层架构思维可概括为 6 个核心关键词:隔离、前置、分层、削峰、分片、兜底。
隔离:业务、系统、数据三层隔离,杜绝秒杀流量雪崩影响全站。 核心是把故障锁在最小范围,牺牲局部,保全整体。
前置:校验、限流、缓存全部上移至 CDN、OpenResty,越上游拦截成本越低。 能在外面拦的,就别放进来;能用低成本组件拦的,就别用贵的组件处理。
分层:漏斗式逐层过滤无效请求,百万流量最终仅少量订单落库。 一层拦不住还有下一层,层层设防,保证最底层的数据库安全。
削峰:预约、验证码、MQ 异步多手段摊平瞬时洪峰。 不硬抗峰值,把脉冲流量拉平,让系统始终工作在舒适区。
分片:库存分片解决 Redis 单 Key 热点瓶颈,动态调度平衡分片库存。 把集中的压力拆散开,用分布式的思路解决热点问题。
兜底:限流、熔断、降级、缓存容灾、数据库多层兜底,极端场景保证核心抢购链路可用。 做最坏的打算,哪怕多个组件出问题,核心功能也不能彻底挂掉。
架构迭代永远贴合业务流量增长:小型秒杀可简化隔离与分片;大促爆款必须完整落地全套分层治理、动态库存、前置 OpenResty 网关方案。技术选型不能盲目堆砌组件,需结合活动规模、流量预估平衡性能与开发运维成本,搭建可长期迭代、稳定抗洪峰的标准化秒杀架构。
真正优秀的秒杀架构,从来不是用了多少高大上的技术,而是用最合适的成本,解决最核心的问题,同时在极端情况下守住底线。