马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
30分钟课程:订单超时关闭实战(Kafka延时队列 + 定时使命赔偿)
课程目的
- 明白订单超时关闭的业务场景与核心需求。
- 掌握基于 Kafka 延时队列与定时使命的关单方案计划。
- 实现高并发场景下的可靠关单逻辑(防重复、幂等性)。
课程内容与时间分配
0~5分钟:课程概述
业务场景与寻衅
- 超时关单:用户下单后未付出,需在指定时间(如30分钟)后主动关闭订单并释放库存。
- 核心问题:
- 精准耽误:如何确保消息在指定时间后被消耗?
- 可靠性:避免消息丢失或重复消耗导致订单状态错误。
- 高性能:支撑每日百万级订单的关单需求。
技术选型
- Kafka 延时队列:利用 Kafka 时间轮(Timer Wheel)实现近似耽误(需外部存储辅助)。
- 定时使命赔偿:兜底扫描未付出订单,防止 Kafka 消息丢失或耽误误差。
5~10分钟:技术难点与核心问题
- Kafka 原生不支持延时队列
- 消息重复消耗
- 分布式系统时钟同步
- 数据一致性
- 关单需同时释放预扣库存、更新订单状态,需事务性保障。
10~25分钟:解决方案与代码实战
1. Kafka延时队列计划(10~15分钟)
方案计划
- 消息分桶:按耽误时间分多个 Topic(如 delay_5m、delay_30m)。
- 生产者逻辑:订单创建时发送消息到对应耽误 Topic。
- 消耗者逻辑:监听耽误 Topic,到期后触发关单。
生产者代码(发送耽误消息)
- @Service
- public class OrderTimeoutProducer {
- @Autowired
- private KafkaTemplate<String, String> kafkaTemplate;
- // 发送延迟消息(按分钟分桶)
- public void sendDelayMessage(String orderId, long delayMinutes) {
- String topic = "delay_" + delayMinutes + "m";
- kafkaTemplate.send(topic, orderId);
- }
- }
- // 订单创建时调用(延迟30分钟)
- orderTimeoutProducer.sendDelayMessage(orderId, 30);
复制代码 消耗者代码(处理关单)
- @KafkaListener(topics = "delay_30m")
- public void handleDelayMessage(String orderId) {
- Order order = orderService.getOrder(orderId);
- if (order.getStatus() == OrderStatus.UNPAID) {
- orderService.closeOrder(orderId); // 关单逻辑(释放库存、更新状态)
- }
- }
复制代码 2. 定时使命赔偿(15~25分钟)
方案计划
- 兜底扫描:每小时扫描一次未付出且未关闭的订单(创建时间 > 30分钟)。
- 分布式锁:防止多节点重复扫描(Redis 锁)。
定时使命代码
- @Scheduled(cron = "0 0/60 * * * ?") // 每小时执行一次
- public void scanUnpaidOrders() {
- String lockKey = "lock:scan_unpaid_orders";
- // 获取分布式锁(Redis 实现)
- if (redisLock.tryLock(lockKey, 60)) {
- try {
- // 查询超过30分钟未支付的订单
- List<Order> orders = orderMapper.selectUnpaidOrders(30);
- for (Order order : orders) {
- orderService.closeOrder(order.getOrderId());
- }
- } finally {
- redisLock.unlock(lockKey);
- }
- }
- }
复制代码 关单幂等性处理
- public void closeOrder(String orderId) {
- // 使用数据库乐观锁确保幂等性
- int rows = orderMapper.updateOrderStatus(
- orderId,
- OrderStatus.UNPAID,
- OrderStatus.CLOSED
- );
- if (rows > 0) {
- stockService.rollbackStock(orderId); // 释放库存
- }
- }
复制代码 25~30分钟:练习与拓展
练习题目
- 动态耽误配置
- 要求:支持不同商品类目设置不同的关单时间(如假造商品5分钟,实物商品30分钟)。
- 消息丢失赔偿
- 场景:Kafka 消息丢失导致未触发关单。
- 使命:优化定时使命扫描逻辑,优先处理 Kafka 未覆盖的订单。
保举拓展方向
- 精准延时队列
- 联合 RocketMQ 的耽误消息(支持18个固定耽误级别)。
- 分库分表优化
- 重试队列计划
- 关单失败时,将订单ID投递到重试队列,最多重试3次。
课程总结
- 延时队列核心逻辑:Kafka 分桶 + 定时使命兜底,平衡性能与可靠性。
- 关键计划:
- 幂等性:通过数据库乐观锁防止重复关单。
- 分布式锁:避免定时使命多节点重复执行。
- 事务性:关单与库存释放需原子化(可联合本地事务表)。
- 实用场景:高并发、允许短暂误差的耽误使命(如订单关单、优惠券逾期)。
课后资源
- Kafka 延时队列参考:Kafka Delayed Message Design
- 完整代码示例:GitHub - 电商关单系统Demo
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |