一道小学算术题
开抢前先做一道算术:100 万请求、50 件商品,意味着 99.995% 的请求从出生那一刻就注定失败。这不是悲观,是设计输入:如果放这 100 万个请求走完全程,就是 100 万次扣库存、几十万笔脏订单、不可预测的数据修复;如果在第一层就拦下 90%,第二层再拦 80%,走到数据库的请求只剩千级——系统就从"扛不住"变成"绰绰有余"。秒杀架构的第一性原理:让注定失败的请求,在最便宜的层失败。
五层漏斗
从外到内,五道闸门各司其职:第一层,页面与 CDN——静态化加本地拦截,让纯浏览流量与重复点击不出端,这一层拦掉的不是"用户",是重复与无效请求;第二层,网关——入口限流加防刷,把总流量钳制在系统容量内;第三层,风控——把脚本与黄牛从真人里筛出去;第四层,Redis 预扣——用内存原子操作扣减库存资格,只有抢到资格的请求才向后走;第五层,MQ 异步下单——把订单落库的速度从"用户等"改成"系统消化",数据库按自己的节奏平稳写入。
| 层级 | 入口流量 | 出口流量 | 主要手段 |
|---|---|---|---|
| 页面/CDN | 100 万 | 40 万 | 静态化、防抖、错峰 |
| 网关 | 40 万 | 20 万 | 限流、黑名单 |
| 风控 | 20 万 | 8 万 | 设备指纹、行为识别 |
| Redis 预扣 | 8 万 | 2000 | Lua 原子扣减 |
| MQ 异步下单 | 2000 | 50 单 | 削峰、幂等落库 |
越早过滤越便宜
漏斗各层的"过滤单价"差得惊人:CDN 拦一个请求,成本几乎为零,还顺手省了带宽;网关拦一个,是一次内存判断;风控拦一个,要查指纹画像,几百微秒;Redis 拦一个,一次原子操作;等到数据库来拦,用的是最贵的行锁竞争和事务回滚。同样的过滤效果,放在外层做是优化,放在内层做是事故——这也是为什么把"扣库存"从数据库提到 Redis、把"限流"从服务提到网关,每一步上移都是数量级的收益。
被拦下的流量去哪了
漏斗拦掉 99% 的请求,但拦下不等于甩脸子:命中限流的返回排队页,"您前面还有 8 万人";未抢到的直接进入售罄态,页面置灰明示"已抢完";愿意等的进候补名单,后续有货自动补。失败的体验也是产品设计的一部分——明确比沉默好,排队比报错好。体验做不好,前面架构省下的成本,客服与舆情会加倍还回来。
骨架搭完,接下来逐层展开。先从最便宜的一层讲起:前端削峰——页面层就该拦下八成流量。
评论 (0)