TL;DR
- 场景: 电商秒杀/抢票场景瞬时流量高峰,读写并发都很高
- 结论: 使用预静态+限流排队;写路径用 Redis Lua 原子预扣+MQ 异步持久化;读路径用多级缓存
- 产出: 秒杀前后端实现清单 + Kafka 生产/消费示例 + Lua 库存扣减脚本框架
应用场景
电商案例 - 高并发秒杀系统响应策略
秒杀前策略:
-
页面静态化处理
- 预生成商品详情页静态 HTML
- 使用 CDN 分发静态资源
-
请求限流与排队
- 分层限流:
- 前端 JS 限制刷新频率
- 网关层限制 IP 请求
- 服务层限制接口调用
- 分层限流:
-
缓存预热
- 将秒杀商品信息预加载到 Redis 缓存
- 使用多级缓存架构
秒杀核心处理:
-
库存扣减优化
- 使用 Redis 原子操作进行预扣减
- Lua 脚本保证原子性
-
订单处理分流
- 使用消息队列进行削峰填谷
- 架构: 请求 → 快速验证 → MQ → 异步订单处理
-
服务隔离与降级
- 独立部署秒杀服务
- 关键降级策略:禁用非核心功能
高并发读请求处理
1. 缓存策略优化
- 多级缓存架构:
- 客户端缓存
- CDN 边缘节点缓存
- 应用层缓存(Redis/Memcached)
- 数据库查询缓存
2. 数据静态处理
- 全静态: 生成 HTML 文件托管在 CDN
- 半静态: 静态模板 + 动态数据片段
3. 智能限流
- 限流维度: 用户 ID、IP、设备指纹、接口级别
- 限流算法: 令牌桶、漏桶、滑动窗口计数
高并发写请求处理
消息队列解决方案
-
流量削峰
- 将突发 10k QPS 写请求暂存到队列
- 数据库按自身节奏消费(如 2000 QPS)
-
异步处理
- 快速响应阶段: 验证用户资格、生成预订单、立即返回
- 异步处理阶段: 实际库存扣减、生成正式订单、通知支付系统
-
系统解耦
- 订单服务只生成订单消息
- 库存服务独立消费消息
- 支付服务监听支付消息
Kafka 实现示例
Producer:
public void handleSeckillRequest(UserRequest request) {
if(!validate(request)) return;
PreOrder preOrder = createPreOrder(request);
kafkaTemplate.send("seckill_orders", preOrder);
return Response.success("抢购请求已接收");
}
Consumer:
@KafkaListener(topics = "seckill_orders")
public void processOrder(PreOrder preOrder) {
try {
inventoryService.reduceStock(preOrder);
orderService.createRealOrder(preOrder);
paymentService.preparePayment(preOrder);
} catch (Exception e) {
retryOrCompensate(preOrder, e);
}
}
削峰填谷
实现流程
-
请求缓冲阶段:
- 生成唯一请求 ID
- 序列化为 JSON 写入 MQ
- 50ms 内返回
-
流量削峰机制:
- 队列作为缓冲区处理瞬时流量(如 100k QPS)
- 设置最大队列积压(如 500k)作为熔断
-
用户体验平衡:
- 显示”预计等待约1分钟”
- 使用 WebSocket 推送结果
- 三种最终状态:成功、失败(售罄)、超时 |
错误速查
| 症状 | 根因 | 修复 |
|---|---|---|
| 超卖/负库存 | 非原子库存扣减 | Redis Lua 原子预扣;DB 乐观锁 |
| 订单成功但丢失/延迟 | MQ 积压或消费者不足 | 增加分区/消费者;隔离重试队列 |
| 重复订单 | 至少一次投递无幂等 | 消费端幂等:唯一索引/去重表 |
| 消息丢失 | 生产者未确认;broker 未持久化 | Kafka: acks=all |
| 5xx 错误/线程池耗尽 | 长同步链路;无快速失败 | 仅同步快速验证+入队;其他异步 |
| Redis CPU 飙升/延迟 | 热 key、Lua 复杂、连接过多 | 分片热 key;本地缓存;连接池调优 |