
1) 【一句话结论】采用微服务架构,订单表设计主键为订单ID并优化索引,库存扣减通过Redis分布式锁避免超卖,缓存用随机过期时间防雪崩,消息队列带指数退避重试,结合Saga模式实现最终一致性,确保高并发下订单处理性能与数据一致性。
2) 【原理/概念讲解】
订单处理系统需应对高并发,核心设计如下:
3) 【对比与适用场景】
| 组件/策略 | 定义 | 特性 | 使用场景 | 注意点 |
|---|---|---|---|---|
| 订单表设计 | 主键为订单ID,按订单ID分库分表,优化索引 | 分库分表提升写入性能,索引加速查询 | 高并发订单系统 | 分片键选择影响数据分布,需合理设计 |
| 分布式锁(库存扣减) | Redis SETNX实现分布式锁,保证并发安全 | 防超卖,高并发下库存扣减安全 | 库存扣减场景 | 锁超时需设置,避免死锁 |
| 缓存随机过期 | 热点数据设置随机过期时间(如5-10分钟内随机) | 防缓存雪崩,避免大量请求落库 | 热门商品订单 | 过期时间需动态调整 |
| 消息队列指数退避 | 消费失败后按指数退避重试(1s→2s→4s...) | 避免消息积压,提升系统稳定性 | 异步处理场景 | 最大重试次数需设置,避免无限重试 |
| Saga补偿幂等 | 补偿事务检查状态(如订单已补偿则跳过) | 确保补偿不重复 | 分布式事务回滚 | 幂等标识需唯一(如订单ID+补偿类型) |
4) 【示例】(伪代码,订单服务处理下单流程):
用户下单请求:POST /api/orders,参数:商品ID=1001,数量=2,用户ID=U001
1. 检查库存(Redis缓存):
- 若缓存存在且未过期:获取库存(如库存=10),判断是否足够(10≥2);
- 若缓存过期:从MySQL读取库存(SELECT stock FROM inventory WHERE product_id=1001),更新Redis缓存(SET key:inventory_1001 value:8 expire:5min+随机时间),再判断库存。
2. 获取分布式锁(Redis SETNX key:lock_order_1001 value:1 timeout:10s):
- 锁成功:执行库存扣减(UPDATE inventory SET stock=stock-1, version=version+1 WHERE product_id=1001 AND stock>=2 AND version=?);
- 锁失败:重试步骤1-2。
3. 写入订单表(MySQL):
INSERT INTO orders (order_id, user_id, product_id, quantity, status, create_time) VALUES (UUID(), U001, 1001, 2, '待支付', NOW());
4. 发布事件(Kafka):
PRODUCE topic:order-created, value:订单ID
5. 库存服务消费事件:
- 检查库存(Redis),扣减库存(同步骤2),发布库存更新事件;
6. 支付服务消费事件:
- 调用第三方支付API(如支付宝),发布支付成功事件;
7. 订单服务消费支付成功事件:
- 更新订单状态为'已支付',删除Redis缓存(或设置过期时间)。
5) 【面试口播版答案】
面试官您好,针对乐歌股份促销季高并发订单场景,我设计的系统采用微服务架构,订单表设计主键为订单ID并优化索引,库存扣减通过Redis分布式锁避免超卖,缓存用随机过期时间防雪崩,消息队列带指数退避重试,结合Saga模式实现最终一致性。具体来说,用户下单时,订单服务先检查库存(缓存+分布式锁),写入订单表并发布事件,库存和支付服务消费事件处理,最后订单服务确认状态,这样既保证了高并发下的性能,又通过分布式锁、缓存策略和Saga模式保证了数据一致性。
6) 【追问清单】
7) 【常见坑/雷区】