🔥《高并发设计:秒杀系统全流程方案》


1️⃣ 秒杀系统的挑战:从单点压力到系统雪崩

场景: 一场 0 元秒杀活动刚上线,1 秒钟涌入 10 万用户请求,仅 100 台服务器瞬间被击垮。

🔥 秒杀系统的三大挑战:

  • 并发洪峰: QPS 突破极限,容易造成网关、数据库雪崩;
  • 库存一致: 多人并发抢购,容易导致超卖、重复下单;
  • 系统稳定性: 单一热点商品可能压垮整条链路。

类比:就像抢春运火车票,每一秒都是“生死时速”。


2️⃣ 流量削峰利器:令牌桶 vs 漏桶

🚰 漏桶算法(Leaky Bucket)

  • 原理: 请求先进入“漏桶”,以固定速率出水处理。
  • 特点: 限速均匀,不能处理突发高峰。

🪙 令牌桶算法(Token Bucket)

  • 原理: 系统以固定速率生成“令牌”,请求必须持有令牌才能通过。
  • 特点: 支持突发流量,控制整体速率。

🧪 Java 示例:Google RateLimiter 实现令牌桶

RateLimiter rateLimiter = RateLimiter.create(100); // 每秒 100 个请求
if (rateLimiter.tryAcquire()) {
    // 执行秒杀逻辑
} else {
    // 拒绝请求
}

✅ 小结:

对比点漏桶令牌桶
限速方式固定出水速率令牌速率 + 突发处理
抗突发能力
秒杀推荐

3️⃣ 秒杀核心:库存扣减的 Redis + Lua 原子方案

🚀 为什么用 Redis?

  • 快(内存级别);
  • 支持并发访问;
  • 支持原子操作(Lua 脚本);

💡 Lua 脚本方案:

-- check_stock.lua
local stock = tonumber(redis.call('get', KEYS[1]))
if stock <= 0 then
  return -1
end
redis.call('decr', KEYS[1])
return 1

Java 调用:

String script = loadScript("check_stock.lua");
Long result = redisTemplate.execute(new DefaultRedisScript<>(script, Long.class), 
        Collections.singletonList("seckill:sku:12345"));

🛡 如何防止超卖 & 重复下单?

  • 设置用户参与标志位 SETNX user:sku:{uid};
  • Redis + Lua 一并执行标志设置与扣减库存;
  • 库存为 0 时,立即 reject。

✅ 小结:

Redis + Lua 是高并发场景下的库存锁原子操作利器。

4️⃣ 热点商品隔离:避免单商品拖垮系统

❗问题:

某个爆款秒杀商品被百万用户盯上,缓存击穿 → 数据库扛不住。

🧯解决方案:

策略说明
缓存预热活动前将商品库存、详情预加载到 Redis 中
缓存分片将热门商品 ID 拆分成多个逻辑片段分流压力
本地缓存 + 限流高频访问前放一层 CaffeineGuava 本地缓存
布隆过滤器防止非法商品 ID 请求击穿缓存

✅ 小结:

热点隔离关键是:提前预热 + 层层缓存 + 限流限并发

5️⃣ 异步下单机制与事务补偿

🚧 同步下单的问题:

  • Redis 扣库存 → 写订单 → 扣减余额 … 全流程太慢!
  • 数据库压力山大,延迟高,失败率增加。

✅ 异步下单设计(削峰填谷)

客户端 → Redis 判断库存 → 放入 MQ 消息队列 → 订单服务异步消费下单

Java MQ 生产:

OrderMessage msg = new OrderMessage(userId, skuId);
rocketMQTemplate.convertAndSend("seckill-order-topic", msg);

订单服务消费:

@RocketMQMessageListener(...)
public class OrderConsumer implements RocketMQListener<OrderMessage> {
    public void onMessage(OrderMessage msg) {
        try {
            orderService.create(msg);
        } catch (Exception e) {
            sendToCompensationTopic(msg); // 异常补偿机制
        }
    }
}

⚠ 补偿机制怎么做?

  • 消费失败消息入“补偿队列”;
  • 后台定时任务重试;
  • 超时未支付订单 → 自动回滚库存。

6️⃣ 分布式限流实战

🌐 接入层限流

  • Nginx:limit_req_zone 配置;
  • Spring Gateway:
filters:
  - name: RequestRateLimiter
    args:
      redis-rate-limiter.replenishRate: 10
      redis-rate-limiter.burstCapacity: 20

☁️ 应用层限流:Sentinel + Redis 滑动窗口

@SentinelResource(value = "seckillResource", blockHandler = "handleBlock")
public String doSeckill(...) {
    // 秒杀逻辑
}

Redis 滑动窗口限流(简化)

List<Long> timestamps = redis.lrange("user:uid", 0, -1);
if (timestamps.countRecent(5s) > 10) {
    return "请求过于频繁";
}

7️⃣ 秒杀系统完整架构图

                +-----------+
                |   网关    |
                +-----------+
                     |
                限流 + 黑名单
                     |
        +------------+-------------+
        |                          |
   热点商品预热                普通商品
        |                          |
     Redis 缓存           Redis 缓存
        |                          |
   ↓(扣库存+限流)             ↓
+-----------+             +-------------+
|  MQ 异步投递 |--------->|  订单微服务  |
+-----------+             +-------------+
                                |
                        数据库写入 + 补偿机制

8️⃣ 常见问题与应对策略

问题应对方案
库存不一致Redis 原子扣减 + DB 最终校验
超卖/重复下单用户限购标志位 + 幂等性校验
MQ 消息丢失消息可靠投递 + 补偿机制
配置更新不生效配合 Nacos 配置中心热更新
分布式锁失效Redisson + WatchDog 自动续期

✅ 总结:构建稳定高可用的秒杀系统关键点

  • ✅ 前端限流 + 接入层保护,挡住大部分无效流量;
  • ✅ Redis + Lua 原子扣库存,确保库存准确;
  • ✅ 异步下单 + MQ 解耦,大幅降低主链路压力;
  • ✅ 热点隔离 + 多级缓存,防止单点拖垮全局;
  • ✅ 限流 + 熔断 + 补偿机制,让系统更具“韧性”。

📌 秒杀系统是系统稳定性设计的“炼金石”,掌握这套设计体系,你将具备应对千万级并发场景的能力。

📚 推荐阅读:

如果你觉得文章对你有帮助,欢迎 点赞 + 收藏 + 转发,更多微服务实战干货持续更新中 💪!

更多推荐