电商平台并发请求系统设计:1件库存应对百万请求防超卖方案设计
电商高并发秒杀场景下避免超卖的系统设计方案
针对单库存、百万级并发请求的场景,核心思路是分层拦截流量,只放极少量合法请求到最终的数据库库存校验层,从架构各个层面杜绝超卖可能:
1. 上层流量削峰,提前拦截无效请求
这一层可以过滤掉90%以上的垃圾流量,避免无效请求占用核心链路资源:
- 前端侧限制:活动开启前隐藏购买入口,开抢后限制同一用户3秒内只能提交1次请求,直接拦截用户重复点击产生的无效请求。
- 接入网关限流:按IP、用户ID维度做流量管控,比如单IP每秒最多放行5次请求,超过阈值直接返回「活动火爆,请稍后再试」,100万请求在这一层至少能挡掉80%。
- 资格前置校验:网关层提前校验用户购买权限(比如是否实名认证、是否符合限购规则),不符合要求的直接拒绝,不需要流转到下游服务。
2. 缓存层库存预扣,拦截绝大多数合法请求
Redis层是核心抗并发的节点,避免请求直接打数据库:
- 活动开启前提前把商品库存(此处为1)预热到Redis中,所有通过上层校验的请求先到Redis做库存扣减。
- 用Redis原子命令
DECR做库存扣减,禁止用「先查库存再判断再修改」的非原子操作:执行DECR product:{商品ID}:stock后,如果返回结果≥0说明扣减成功,拿到后续创建订单的资格;返回结果<0直接返回库存不足。 - 极端场景下可以加分布式锁做兜底,用
SETNX product:{商品ID}:lock 1 EX 3命令,只有拿到锁的请求才能进入后续流程,进一步控制到数据库层的请求量。
3. 数据库层最终校验,从底层杜绝超卖
经过前两层拦截后,最终到数据库层的请求最多只有个位数,完全不会产生性能压力:
- 数据库库存字段设置为无符号整数,从数据结构层面禁止库存出现负数。
- 扣减库存的SQL加乐观锁校验,示例代码如下:
UPDATE goods_stock SET stock = stock - 1 WHERE goods_id = {商品ID} AND stock >= 1;
- 如果SQL执行影响行数为1,说明库存扣减成功,正常生成订单;如果影响行数为0,说明库存已经被其他用户扣减,返回库存不足的同时回补Redis中的缓存库存。
4. 兜底一致性保障
- 订单设置支付超时自动取消规则,超时未支付的订单自动回补Redis和数据库的库存,避免用户占库存不支付导致的商品浪费。
- 每日定时跑库存对账任务,对比Redis缓存库存和数据库实际库存的差值,出现不一致时以数据库库存为准修正缓存,避免缓存数据异常导致的超卖或少卖。
内容的提问来源于stack exchange,提问作者Harsh Verma
相关产品推荐
相关产品推荐

