侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1824 篇文章
  • 累计收到 0 条评论

设计一个支持高并发秒杀活动的电商系统

2025-12-11 / 0 评论 / 4 阅读

题目

设计一个支持高并发秒杀活动的电商系统

信息

  • 类型:问答
  • 难度:⭐⭐⭐

考点

高并发处理,分布式系统设计,缓存策略,限流与降级,数据一致性

快速回答

设计高并发秒杀系统的核心要点:

  • 分层削峰:通过CDN、网关、队列逐层过滤流量
  • 读优化:使用Redis缓存商品库存和活动信息
  • 写优化:采用异步扣减库存(Redis预减+MQ持久化)
  • 限流防护:在网关层实现令牌桶/漏桶限流
  • 熔断降级:对非核心服务(如推荐系统)降级
  • 最终一致性:通过事务消息保证订单-库存一致性
## 解析

1. 系统架构设计

分层架构

  • 客户端层:静态资源CDN缓存,按钮防重复点击
  • 接入层:Nginx反向代理+Lua脚本实现限流
  • 服务层:微服务拆分(秒杀服务独立部署)
  • 数据层:Redis集群+MySQL分库分表
// 网关层限流示例(Sentinel)
@SentinelResource(value = "seckillFlow", blockHandler = "handleBlock")
public String seckillApi(String itemId) {
    // 业务逻辑
}

2. 核心难点解决方案

2.1 库存超卖问题

  • Redis原子操作:使用Lua脚本保证原子性
  • 分段扣减:将库存拆分为多个子库存段
-- Redis库存扣减Lua脚本
local key = KEYS[1]
local quantity = tonumber(ARGV[1])
if redis.call('get', key) >= quantity then
    return redis.call('decrby', key, quantity)
else
    return -1
end

2.2 高并发写优化

  • 请求进入RabbitMQ/Kafka削峰
  • Worker服务异步处理订单
  • 库存预扣:Redis扣减成功后再发MQ
// 伪代码:秒杀核心流程
public void handleSeckillRequest(String userId, String itemId) {
    // 1. 校验用户资格(频率限制)
    // 2. Redis预减库存(Lua脚本)
    // 3. 发送MQ消息:包含秒杀凭证
    // 4. 异步创建订单(Worker服务)
}

3. 关键防护机制

3.1 限流策略

  • 用户维度:同一用户10s内仅允许1次请求
  • IP维度:滑动窗口限制异常IP
  • 系统维度:QPS阈值动态调整

3.2 降级方案

  • 一级降级:关闭实时库存显示
  • 二级降级:排队机制(返回等待队列位置)
  • 三级降级:静态化兜底页面

4. 数据一致性保障

最终一致性方案

  1. Redis扣减库存成功
  2. 发送事务消息到RocketMQ
  3. 订单服务消费消息创建订单
  4. 定时任务核对库存与订单差异
// RocketMQ事务消息示例
transactionMQProducer.sendMessageInTransaction(msg, (arg) -> {
    try {
        // 执行本地事务(创建订单)
        return LocalTransactionState.COMMIT_MESSAGE;
    } catch (Exception e) {
        return LocalTransactionState.ROLLBACK_MESSAGE;
    }
});

5. 常见错误与规避

  • 错误1:直接查询数据库验证库存
    规避:所有读操作走Redis缓存
  • 错误2:同步调用支付服务
    规避:支付操作异步化,秒杀成功即返回
  • 错误3:单点限流
    规避:分布式限流(Redis+Lua)

6. 扩展优化方向

  • 库存预热:提前加载热点商品到本地缓存
  • 动态扩容:Kubernetes+HPA自动扩缩容
  • 作弊防控:风控系统实时检测机器人行为
  • 压测优化:全链路压测+混沌工程