【JAVA架构师成长之路】【电商系统实战】第9集:订单超时关闭实战(Kafka延 ...

打印 上一主题 下一主题

主题 982|帖子 982|积分 2946

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

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,到期后触发关单。
生产者代码(发送耽误消息)
  1. @Service  
  2. public class OrderTimeoutProducer {  
  3.     @Autowired  
  4.     private KafkaTemplate<String, String> kafkaTemplate;  
  5.     // 发送延迟消息(按分钟分桶)  
  6.     public void sendDelayMessage(String orderId, long delayMinutes) {  
  7.         String topic = "delay_" + delayMinutes + "m";  
  8.         kafkaTemplate.send(topic, orderId);  
  9.     }  
  10. }  
  11. // 订单创建时调用(延迟30分钟)  
  12. orderTimeoutProducer.sendDelayMessage(orderId, 30);  
复制代码
消耗者代码(处理关单)
  1. @KafkaListener(topics = "delay_30m")  
  2. public void handleDelayMessage(String orderId) {  
  3.     Order order = orderService.getOrder(orderId);  
  4.     if (order.getStatus() == OrderStatus.UNPAID) {  
  5.         orderService.closeOrder(orderId); // 关单逻辑(释放库存、更新状态)  
  6.     }  
  7. }  
复制代码

2. 定时使命赔偿(15~25分钟)

方案计划


  • 兜底扫描:每小时扫描一次未付出且未关闭的订单(创建时间 > 30分钟)。
  • 分布式锁:防止多节点重复扫描(Redis 锁)。
定时使命代码
  1. @Scheduled(cron = "0 0/60 * * * ?") // 每小时执行一次  
  2. public void scanUnpaidOrders() {  
  3.     String lockKey = "lock:scan_unpaid_orders";  
  4.     // 获取分布式锁(Redis 实现)  
  5.     if (redisLock.tryLock(lockKey, 60)) {  
  6.         try {  
  7.             // 查询超过30分钟未支付的订单  
  8.             List<Order> orders = orderMapper.selectUnpaidOrders(30);  
  9.             for (Order order : orders) {  
  10.                 orderService.closeOrder(order.getOrderId());  
  11.             }  
  12.         } finally {  
  13.             redisLock.unlock(lockKey);  
  14.         }  
  15.     }  
  16. }  
复制代码
关单幂等性处理
  1. public void closeOrder(String orderId) {  
  2.     // 使用数据库乐观锁确保幂等性  
  3.     int rows = orderMapper.updateOrderStatus(  
  4.         orderId,  
  5.         OrderStatus.UNPAID,  
  6.         OrderStatus.CLOSED  
  7.     );  
  8.     if (rows > 0) {  
  9.         stockService.rollbackStock(orderId); // 释放库存  
  10.     }  
  11. }  
复制代码

25~30分钟:练习与拓展


练习题目


  • 动态耽误配置

    • 要求:支持不同商品类目设置不同的关单时间(如假造商品5分钟,实物商品30分钟)。

  • 消息丢失赔偿

    • 场景:Kafka 消息丢失导致未触发关单。
    • 使命:优化定时使命扫描逻辑,优先处理 Kafka 未覆盖的订单。

保举拓展方向


  • 精准延时队列

    • 联合 RocketMQ 的耽误消息(支持18个固定耽误级别)。

  • 分库分表优化

    • 按订单创建时间分表,提升定时使命扫描效率。

  • 重试队列计划

    • 关单失败时,将订单ID投递到重试队列,最多重试3次。


课程总结



  • 延时队列核心逻辑:Kafka 分桶 + 定时使命兜底,平衡性能与可靠性。
  • 关键计划

    • 幂等性:通过数据库乐观锁防止重复关单。
    • 分布式锁:避免定时使命多节点重复执行。
    • 事务性:关单与库存释放需原子化(可联合本地事务表)。

  • 实用场景:高并发、允许短暂误差的耽误使命(如订单关单、优惠券逾期)。
课后资源


  • Kafka 延时队列参考:Kafka Delayed Message Design
  • 完整代码示例:GitHub - 电商关单系统Demo

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

千千梦丶琪

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表