【JAVA架构师成长之路】【电商系统实战】第9集:订单超时关闭实战(Kafka延时队列 + 定时任务补偿)
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
相关文章:
【JAVA架构师成长之路】【电商系统实战】第9集:订单超时关闭实战(Kafka延时队列 + 定时任务补偿)
30分钟课程:订单超时关闭实战(Kafka延时队列 定时任务补偿) 课程目标 理解订单超时关闭的业务场景与核心需求。掌握基于 Kafka 延时队列与定时任务的关单方案设计。实现高并发场景下的可靠关单逻辑(防重复、幂等性)。…...
《探秘课程蒸馏体系“三阶训练法”:解锁知识层级递进式迁移的密码》
在人工智能与教育科技深度融合的时代,如何高效地实现知识传递与能力提升,成为众多学者、教育工作者以及技术专家共同探索的课题。课程蒸馏体系中的“三阶训练法”,作为一种创新的知识迁移模式,正逐渐崭露头角,为解决这…...
K8s 1.27.1 实战系列(六)Pod
一、Pod介绍 1、Pod 的定义与核心设计 Pod 是 Kubernetes 的最小调度单元,由一个或多个容器组成,这些容器共享网络、存储、进程命名空间等资源,形成紧密协作的应用单元。Pod 的设计灵感来源于“豌豆荚”模型,容器如同豆子,共享同一环境但保持隔离性。其核心设计目标包括…...
Java CountDownLatch 用法和源码解析
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,…...
Unity引擎使用HybridCLR(华佗)热更新
大家好,我是阿赵。 阿赵我做手机游戏已经有十几年时间了。记得刚开始从做页游的公司转到去做手游的公司,在面试的时候很重要的一个点,就是会不会用Lua。使用Lua的原因很简单,就是为了热更新。 热更新游戏内容很重要。如果…...
深度学习进阶:神经网络优化技术全解析
文章目录 前言一、优化问题的本质1.1 目标1.2 挑战 二、梯度下降优化算法2.1 基础SGD2.2 动量法2.3 Adam优化器 三、正则化技术3.1 L2正则化3.2 Dropout 四、学习率调度4.1 为什么要调度?4.2 指数衰减4.3 ReduceLROnPlateau 五、实战优化:MNIST案例5.1 完…...
肿瘤检测新突破:用随机森林分类器助力医学诊断
前言 你有没有想过,科技能不能在肿瘤检测中发挥巨大的作用?别着急,今天我们将带你走进一个“聪明”的世界,通过随机森林分类器进行肿瘤检测。对,你没听错,机器学习可以帮助医生更快、更准确地判断肿瘤是良性还是恶性,就像医生口袋里的“超级助手”一样,随时准备提供帮…...
DeepSeek学习 一
DeepSeek学习 一 一、DeepSeek是什么?二、Deepseek可以做什么?模型理解提问内容差异使用原则 模式认识三、如何提问?RTGO提示语结构CO-STAR提示语框架DeepSeek R1提示语技巧 总结 一、DeepSeek是什么? DeepSeek是一家专注通用人工…...
编程考古-Borland历史:《.EXE Interview》对Anders Hejlsberg关于Delphi的采访内容(上)
为了纪念Delphi在2002年2月14日发布的25周年(2020.2.12),这里有一段由.EXE杂志编辑Will Watts于1995年对Delphi首席架构师Anders Hejlsberg进行的采访记录。在这次采访中,Anders讨论了Delphi的设计与发展,以及即将到来的针对Windows 95的32位版本。 问: Delphi是如何从T…...
高并发之接口限流,springboot整合Resilience4j实现接口限流
添加依赖 <dependency><groupId>io.github.resilience4j</groupId><artifactId>resilience4j-spring-boot2</artifactId><version>1.7.0</version> </dependency><dependency><groupId>org.springframework.boot…...
电脑如何拦截端口号,实现阻断访问?
如果你弟弟喜欢玩游戏,你可以查询该应用占用的端口,结合以下方法即可阻断端口号,让弟弟好好学习,天天向上! 拦截端口可以通过防火墙和路由器进行拦截 ,以下是常用方法: 方法 1:使用…...
RK3588 安装ffmpeg6.1.2
在安装 ffmpeg 在 RK3588 开发板上时,你需要确保你的开发环境(例如 Ubuntu、Debian 或其他 Linux 发行版)已经设置好了交叉编译工具链,以便能够针对 RK3588 架构编译软件。以下是一些步骤和指导,帮助你安装 FFmpeg: 1. 安装依赖项 首先,确保你的系统上安装了所有必要的…...
SQL SELECT DISTINCT 语句
在 SQL 中,SELECT DISTINCT 语句用于从表中查询不重复的值。这对于需要从数据库检索唯一值时非常有用。DISTINCT 关键字会去除结果集中重复的行,只返回唯一的记录。 SELECT DISTINCT column1, column2, ... FROM table_name; column1, column2, ... 是…...
MELON的难题
MELON的难题 真题目录: 点击去查看 E 卷 200分题型 题目描述 MELON有一堆精美的雨花石(数量为n,重量各异),准备送给S和W。MELON希望送给俩人的雨花石重量一致,请你设计一个程序,帮MELON确认是否能将雨花石平均分配。 输入描述 第1行输入为雨花石个数: n,0 < n &l…...
Restful 接口设计规范
一、资源与 URL 1. 使用名词表示资源 URL 应该以名词为主,用来表示具体的资源,而不是动词。例如,/users 表示用户资源集合,/users/{id} 表示单个用户资源。 2. 采用复数形式 一般来说,资源的 URL 应该使用复数形式…...
Java后端高频面经——Spring、SpringBoot、MyBatis
Spring定义一个Bean有哪些方法?依赖注入有哪些方法? (1)定义Bean的方法 注解定义Bean,Component 用于标记一个类作为Spring的bean。当一个类被Component注解标记时,Spring会将其实例化为一个bean࿰…...
扩散模型中三种加入条件的方式:Vanilla Guidance,Classifier Guidance 以及 Classifier-Free Guidance
扩散模型主要包括两个过程:前向扩散过程和反向去噪过程。前向过程逐渐给数据添加噪声,直到数据变成纯噪声;反向过程则是学习如何从噪声中逐步恢复出原始数据。在生成过程中,模型从一个随机噪声开始,通过多次迭代去噪&a…...
Banana Pi OpenWRT One Wifi6 OpenWrt社区官方开源路由器评测
第一款不可破解、开源、版权软件、符合 FCC、CE 和 RoHS 的维修权路由器 OpenWRT项目今年已经20岁了,为了纪念这一时刻,Banana Pi OpenWrt One/AP-24.XY路由器开发系统已经上市。这是OpenWRT团队与硬件公司的第一个联合项目。选择 Banana Pi,…...
9.1go结构体
Go不是完全面向对象的,没有类的概念,所以结构体应该承担了更多的责任。 结构体定义 使用 type 和 struct 关键字定义: type Person struct { Name string Age int } 字段可以是任意类型,包括其他结构体或指针。 字段名以大写…...
Manus全球首个通用Agent,Manus AI:Agent应用的ChatGPT时刻
文章目录 前言Manus AI: 全球首个通用AgentManus AI: 技术架构与创始人经历AI Agent的实现框架与启示AI Agent的发展预测行业风险提示 前言 这是一篇关于Manus AI及其在通用人工智能领域的应用和前景的报告,主要介绍了Manus AI的产品定位、功能、技术架构、创始人经…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式
今天是关于AI如何在教学中增强学生的学习体验,我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育,这并非炒作,而是已经发生的巨大变革。教育机构和教育者不能忽视它,试图简单地禁止学生使…...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...
Python竞赛环境搭建全攻略
Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型(算法、数据分析、机器学习等)不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...
第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10+pip3.10)
第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10pip3.10) 一:前言二:安装编译依赖二:安装Python3.10三:安装PIP3.10四:安装Paddlepaddle基础框架4.1…...
ui框架-文件列表展示
ui框架-文件列表展示 介绍 UI框架的文件列表展示组件,可以展示文件夹,支持列表展示和图标展示模式。组件提供了丰富的功能和可配置选项,适用于文件管理、文件上传等场景。 功能特性 支持列表模式和网格模式的切换展示支持文件和文件夹的层…...
