架构 · 高频 5/5

如何设计一个秒杀系统?

秒杀系统要先削峰,再隔离核心链路,最后用库存预扣、异步下单、限流降级和幂等机制保证系统不被瞬时流量压垮。

简短答案

秒杀系统要先削峰,再隔离核心链路,最后用库存预扣、异步下单、限流降级和幂等机制保证系统不被瞬时流量压垮。

详细解析

秒杀的核心矛盾是瞬时流量远大于真实库存。设计时应把读流量、排队流量和写库流量分层处理。

关键设计

  • 入口层:验证码、风控、用户限频、静态资源 CDN。
  • 应用层:本地缓存商品信息,令牌桶或滑动窗口限流。
  • 库存层:Redis 预扣库存,扣减成功再进入 MQ。
  • 订单层:消费 MQ 异步创建订单,使用唯一键和业务流水保证幂等。
  • 兜底层:库存回补、超时关单、降级提示和监控告警。

面试回答模板

我会先说明秒杀不是简单加机器,而是把流量削峰、库存扣减、订单创建和支付链路拆开。入口做限流和风控,库存用 Redis 做原子预扣,成功后写入 MQ,订单服务异步落库,并用幂等键避免重复下单。最后补充监控、降级和库存回补机制。

代码示例

Long stock = redisTemplate.opsForValue().decrement(stockKey);
if (stock == null || stock < 0) {
    redisTemplate.opsForValue().increment(stockKey);
    throw new SoldOutException();
}
messageQueue.send(new CreateOrderCommand(userId, skuId, requestId));

易错点

  • 直接让所有请求打到数据库扣库存。
  • 只说 Redis,不说明库存和数据库最终一致性。
  • 忽略重复点击、消息重复消费和支付回调幂等。

常见追问

为什么不用数据库直接扣库存?

数据库可以保证强一致性,但在秒杀峰值下容易成为瓶颈。更常见做法是 Redis 预扣削峰,再通过异步订单和补偿机制保证最终一致。

如何避免超卖?

库存扣减必须是原子操作,数据库层要有条件更新或唯一约束兜底,消息消费也要幂等。

相关题目

继续刷题
架构设计 架构 ★★★

架构设计面试专题

架构设计面试专题 是 架构设计 中需要重点复习的条目,已从金山文档目录导入,后续可在后台补充完整答案、代码示例和图片。