资讯动态

面试官必问:秒杀系统的后端架构到底怎么设计?

发布时间:2026/9/11 4:40:05 来源:尧图企业网站定制
秒杀系统是面试中的高频题因为它能在短时间内把高并发、缓存、消息队列、分布式锁、数据库瓶颈全部串起来。很多人一上来就说“用 Redis 扣库存然后发 MQ 异步下单”但面试官真正想听的是你如何一层层把流量削掉、把系统压住。下面从架构分层的角度拆解一个可落地的秒杀后端设计。第一层入口限流与防刷秒杀开始瞬间流量可能是平时的几百倍绝不能让它直接打到后端。首先在网关层做限流比如 Nginx 的limit_req或 API 网关的令牌桶按用户维度、IP 维度、接口维度分别设阈值。同时秒杀 URL 要动态化避免被脚本提前拿到加验证码或答题把机器流量挡在门外。对于同一用户短时间重复请求用 Redis 做setnx去重只放行第一次。这一层的目标是把 90% 的无效流量消灭在入口。第二层缓存预热与库存扣减库存不能直接查数据库。秒杀开始前把商品库存、状态、限购数量预热到 Redis。扣库存必须保证原子性推荐用 Lua 脚本lua复制下载local stock redis.call(get, KEYS[1]) if not stock or tonumber(stock) 0 then return 0 end redis.call(decr, KEYS[1]) return 1Lua 脚本在 Redis 中单线程执行天然避免并发超卖。但单 key 库存会成为热点如果 QPS 极高可以分段库存把 1000 件库存拆成 10 个 key每个 100 件请求按用户 ID 哈希到不同 key分散压力。扣减成功后记录用户购买标记防止重复下单。第三层消息队列异步下单Redis 扣减成功不代表订单创建成功。如果同步写数据库数据库根本扛不住。正确做法是扣减库存后立即向 MQ 发送一条消息内容包含用户 ID、商品 ID、秒杀令牌然后直接返回“排队中”。下游订单服务消费消息落库创建订单再异步通知用户。这样前端请求的 RT 从几百毫秒降到几毫秒系统吞吐量大幅提升。消息队列选型上RocketMQ 支持事务消息Kafka 吞吐更高。关键是要保证消息不丢、不重复。生产者用确认机制消费者做幂等——可以用“用户 ID 商品 ID”作为唯一键插入订单前先查重或利用数据库唯一索引。第四层数据库最终一致订单落库后还需要扣减真实库存。这里不能再用 Redis 的库存而是数据库的库存字段。由于 MQ 已经削峰数据库压力可控。采用“乐观锁 库存判断”sql复制下载UPDATE stock SET count count 1 WHERE goods_id ? AND count 1;如果影响行数为 0说明库存不足触发回滚删除 Redis 中的购买标记补偿库存。为了最终一致可以引入本地消息表或定时对账确保 Redis、MQ、数据库三者的状态最终吻合。第五层降级与兜底秒杀系统必须有 Plan B。如果 Redis 挂了直接降级为“活动繁忙请稍后再试”而不是拖垮整个服务。如果 MQ 堆积可以动态扩容消费者或临时关闭非核心商品。数据库连接池要设上限避免慢查询拖死应用。此外监控告警必不可少Redis 库存、MQ 堆积量、订单创建成功率、接口 RT 都要实时上报。面试加分点面试官往往还会追问如何防止超卖——Redis Lua 数据库乐观锁双重保障。如何防止少卖——定时对账补偿未支付订单。如何保证幂等——唯一索引 状态机。如何处理热点 key——库存分段 本地缓存。这些细节能体现你对生产环境的理解。总结秒杀系统的核心思想是分层过滤、异步削峰、最终一致。入口限流挡住大部分流量Redis 原子扣减保证不超卖MQ 异步下单提升吞吐数据库乐观锁兜底降级方案保证可用性。每一层只做自己擅长的事不把压力传给下一层。面试时如果你能按这个脉络讲清楚而不是堆砌技术名词面试官一定会眼前一亮。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价