秒杀与抢购
→ 返回 高并发
电商秒杀(双 11、限量款、iPhone 首发)与 12306 抢票 同属 强一致库存 ,但链路更短、SKU 更碎、营销流量更不可预测。共性是不能超卖 ;差异是购物车弱、下单极快、失败率极高 。
场景特征
特征 说明 瞬时流量 活动开始秒级涌入 成功率极低 库存千级、参与百万级 热点 SKU 单商品库存 key 极热 羊毛党 / 脚本 需风控、令牌、人机验证 体验 「排队中」「已售罄」要明确快速
解决方案总览
活动页 CDN 静态化
▼
网关限流 + 风控(设备指纹、黑名单)
▼
秒杀令牌(排队页发放,持令牌才可下单)
▼
Redis 预扣库存(Lua 原子 DECR)或 DB 乐观锁
▼
创建订单(幂等)→ 支付超时 MQ 回滚库存
1. 页面与流量
手段 说明 静态化 商品介绍、规则页走 CDN,动态库存接口独立 按钮防重 前端禁用连点 + 服务端幂等键 答题 / 验证码 活动开始前过滤机器流量
2. 秒杀令牌(数据层外缓冲)
与 12306 购票令牌同族:
用户点击「立即抢购」
→ 进入排队(Redis 计数 + 随机延迟)
→ 成功则下发 token(JWT / 随机串,短 TTL 60s)
→ 仅带 token 的请求可访问下单 API
参数 建议 令牌速率 按库存与预估转化率反推,宁可少放不可打穿 TTL 60~120 秒,过期需重新排队
3. 库存扣减
Redis 预扣(高并发首选)
-- KEYS[1]=stock:sku:1001 ARGV[1]=扣减数量
local s = tonumber (redis. call ( 'GET' , KEYS[ 1 ]) or '0' )
if s < tonumber (ARGV[ 1 ]) then return 0 end
redis. call ( 'DECRBY' , KEYS[ 1 ], ARGV[ 1 ])
return 1
成功后再 同步写订单 ;失败直接返回「已售罄」。
数据库兜底
订单表唯一约束 (user_id, activity_id) 防重复购买
定时对账 Redis 库存与 DB remain
热点 SKU
手段 说明 库存分桶 stock:sku:1001:bucket:{0..7} 扣减后汇总本地缓存「已售罄」 库存为 0 后各节点短路,保护 Redis
4. 异步与降级
环节 同步 / 异步 扣库存 + 创单 同步 发短信、积分、推荐 MQ 异步 支付超时 延迟队列释放库存
过载时:关闭非核心接口 ,秒杀接口独立集群(舱壁)。
与 12306 对照
秒杀 12306 查询量 中(商品页) 极高(余票) 排队 常见 必备 库存行 SKU 级 车次×席别×日期
检查清单
相关