ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Lottery 抽奖系统:基于 XXL-JOB 扫描库表补偿发货单 MQ 消息的可靠性保障实践

Lottery 抽奖系统:基于 XXL-JOB 扫描库表补偿发货单 MQ 消息的可靠性保障实践 文档教程后端【免费下载链接】CodeGuide:books: 本代码库是作者小傅哥多年从事一线互联网 Java 开发的学习历程技术汇总旨在为大家提供一个清晰详细的学习教程侧重点更倾向编写Java核心内容。如果本仓库能为您提供帮助请给予支持(关注、点赞、分享)项目地址https://gitcode.com/gh_mirrors/code/CodeGuide点击查看免费下载导读本文围绕 Lottery 分布式抽奖系统DDD 四层架构 分库分表 Kafka XXL-JOB中的发货单 MQ 消息补偿场景展开讲解如何利用分布式任务调度平台 XXL-JOB 周期性扫描分库分表下的发货单数据对发送失败的 MQ 消息与迟迟未发送的 MQ 消息进行补偿发送从而保障抽奖结果落库到异步发奖全流程的最终一致性。读完本文你将掌握扫描库表 补偿发送这一类 MQ 可靠性兜底方案的落地思路包括分库分表组件的库表路由扩展、XXL-JOB 执行器任务开发与调度配置。一、为什么需要补偿 MQ 消息在第 第16节使用MQ解耦抽奖发货流程 中抽奖系统已经通过 Kafka 把抽奖与发奖两个环节解耦用户抽奖完成后中奖结果先落库随后发送一条发货单消息Topic 为lottery_invoice下游消费者再异步处理发货流程避免一个流程过长导致用户一直等待。但引入消息队列后全流程的可靠性就取决于消息是否真的发送成功。在真实生产中MQ 发送可能面临网络抖动、Broker 异常、应用宕机等场景一旦消息发送失败而发奖环节又没有收到消息用户就会中奖但不发货这是营销活动中不可接受的故障。为此第16节在抽奖结果表user_strategy_export上新增了状态字段mq_state在数据库表user_strategy_export添加字段mq_state这个字段用于发送 MQ 成功更新库表状态如果 MQ 消息发送失败则需要通过定时任务补偿 MQ 消息。这一字段正是本篇文章补偿任务的判读依据——消息发送成功则把状态更新为成功发送失败或尚未发送则保持待补偿状态等待定时任务扫描兜底。二、补偿任务的整体流程本节的补偿任务完成的是整个抽奖活动中关于中奖结果落库 → 发送 MQ → 出现问题时补偿发送的部分其整体流程如下图所示从图中可以看到完整的闭环逻辑触发起点Worker 扫描表发送状态进行补偿发送 MQ并行扫描多个库由于系统采用了分库分表任务需要同时扫描 1 库、2 库等各个分库扫描多张表每个库下扫描 4 张表对应user_strategy_export_001~004读取未发送 MQ 的数据发送 MQ 消息对扫描出的待补偿数据执行消息发送结果回写根据发送结果更新库表状态——发送成功 → 更新表MQ 状态成功发送失败 → 更新表MQ 状态失败等待下一次任务继续补偿。在 MQ 消息补偿的过程中会把发送失败的消息和迟迟没有发送的消息都进行补偿从而保障全流程的可靠性。三、开发准备扩展分库分表组件支持指定库表扫描1. 为什么需要扩展路由组件因为需要扫描库表也就是循环的方式把每个库下的多张表中的每条用户记录都进行扫描所以需要在分库分表组件中提供出可以设置路由到的库和表的能力这样就可以满足我们扫描的动作了。本项目使用的是自研的 db-router-spring-boot-starter 数据库路由组件它基于散列算法、数据源切换、AOP 切面与 SpringBoot Starter 机制实现。常规的业务写入与查询都会通过路由注解自动路由到正确的库表但补偿任务恰恰相反——它需要遍历所有库、所有表因此必须支持手动指定路由到某个库、某张表的硬编码路由方式才能逐库逐表地扫描。2. 硬编码路由的用途这类指定库表扫描的能力在第 第11节声明事务领取活动领域开发 中已经有过铺垫路由组件扩展了硬编码路由用于支撑声明式事务场景。而本节的补偿任务进一步复用了这套能力——把扫描动作拆解为N 个库 × M 张表的循环每次循环都显式指定当前要扫描的库和表再配合 MyBatis 查询出该表下所有未发送或发送失败的记录。从源码结构看补偿扫描与常规路由是同一套机制的两面常规请求按业务键自动路由到单库单表补偿任务则按任务参数强制路由到指定库表从而实现对全量数据的遍历。四、在应用层添加 LotteryXxlJob 补偿任务1. 任务定位在 application 应用层下的worker包LotteryXxlJob中添加关于扫描库表补偿消息发送的任务。这与第 第17节引入xxl-job处理活动状态扫描 中引入的 XXL-JOB 分布式任务调度平台属于同一套任务体系只是处理不同的业务场景上一节的任务扫描活动状态审核通过→活动中、已过期→关闭本节的任务则扫描发货单消息状态。2. 任务核心逻辑拆解一个完整的补偿任务在代码实现上通常包含以下几个环节可结合本仓库 Lottery 项目的 DDD 分层结构理解环节实现要点对应仓库脉络遍历分库通过路由组件循环设置 dbIdx逐库扫描db-router 分库分表遍历分表每个库下循环user_strategy_export_001~004四张表库表设计见 第04节抽奖活动策略库表设计查询待补偿数据按mq_state状态筛选出发送失败/未发送的记录状态字段引入见 第16节补偿发送 MQ重新发送lottery_invoiceTopic 消息Kafka 环境见 第15节搭建MQ消息组件Kafka服务环境回写发送状态发送成功/失败分别更新库表 MQ 状态形成流程闭环3. 补偿发送时的幂等性保障补偿任务重复扫描执行是常态因此重发消息必须保证下游消费的幂等。这一点在项目面试问答lottery/notes.md中也有体现——抽奖系统 mq 重发的时候是怎么保证幂等性是高频面试题。常规的保障手段包括以中奖记录的业务主键作为消息唯一键下游消费时先查状态再处理以及结合库表mq_state状态做并发控制确保同一条发货单只被成功处理一次。五、把补偿任务配置到 XXL-JOB 调度后台开发完成后需要把任务配置到 XXL-JOB 任务调度后台中关于任务的配置方式在上一个章节 第17节 中已做讲述。这里汇总一下 XXL-JOB 与本任务相关的核心能力方便配置时对照执行器注册执行器会周期性自动注册任务调度中心自动发现并触发执行也支持手动录入执行器地址触发策略提供 Cron 触发、固定间隔触发、固定延时触发、API事件触发、人工触发、父子任务触发等阻塞处理策略调度过于密集、执行器来不及处理时可选择单机串行默认、丢弃后续调度、覆盖之前调度任务失败重试支持自定义失败重试次数任务失败时按预设次数主动重试分片广播任务路由策略选择分片广播时一次调度会广播触发集群中所有执行器执行一次任务可根据分片参数开发分片任务非常适合多库多表扫描这种大数据量操作——每个分片负责一部分库表可显著提升补偿吞吐故障转移路由策略选择故障转移时执行器集群中某台机器故障会自动 Failover 到正常执行器。对本节的补偿任务而言建议关注两点配置Cron 表达式按照业务容忍的补偿时延设置扫描频率例如每分钟或每几分钟一次让发送失败的消息和迟迟没有发送的消息都能尽快被补偿路由策略如果补偿数据量大可以选用分片广播利用多个执行器并行扫描不同库表。六、运行环境的准备与部署参考补偿任务依赖 Kafka 与 XXL-JOB 环境相关命令与部署方式在仓库中均有完整记录Kafka 环境Topic 创建来自 第15节 与 第16节启动zkbin/zookeeper-server-start.sh -daemon config/zookeeper.properties 启动kafkabin/kafka-server-start.sh -daemon config/server.properties 创建topicbin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic lottery_invoiceXXL-JOB 调度中心Docker 部署示例来自 Part-5 部署环境 xxl-jobdocker pull xuxueli/xxl-job-admin:2.3.0 docker run -e PARAMS --server.port7397 --spring.datasource.urljdbc:mysql://172.17.0.6:3306/xxl_job?useUnicodetruecharacterEncodingUTF-8serverTimezoneGMT%2B8 --spring.datasource.usernameroot --spring.datasource.password123456 --xxl.job.accessTokenxdsl3ewi3al1oehxmo68pqxer -p 7397:7397 -v /logs/xxl-job:/data/applogs --name xxl-job-admin --restartalways -d xuxueli/xxl-job-admin:2.3.0部署时需要先准备 MySQL 环境并导入 xxl-job 的初始化 SQL再启动调度中心最后在 Lottery 应用中配置执行器并注册任务。七、总结本节第18节扫描库表补偿发货单 MQ 消息是 Lottery 抽奖系统MQ 解耦发奖链路的最后一块可靠性拼图其核心思路可以概括为状态可追踪通过user_strategy_export.mq_state字段记录每条发货单消息的发送状态这是补偿判定的依据能力可遍历扩展 db-router 路由组件支持指定库表扫描让定时任务可以逐库逐表遍历全部数据补偿成闭环借助 XXL-JOB 周期性触发把发送失败、迟迟未发送的消息重新发送并根据结果回写状态形成扫描 → 发送 → 回写的可靠闭环。从第15节搭建 Kafka、第16节 MQ 解耦发货、第17节引入 XXL-JOB到本节实现消息补偿整个异步化 兜底补偿的可靠性体系才算完整落地。这套扫描库表补偿消息的方案不局限于抽奖场景凡是本地落库 异步发送 需要保证最终一致的 MQ 应用都可以复用同样的设计思路。赞分享文档教程后端【免费下载链接】CodeGuide:books: 本代码库是作者小傅哥多年从事一线互联网 Java 开发的学习历程技术汇总旨在为大家提供一个清晰详细的学习教程侧重点更倾向编写Java核心内容。如果本仓库能为您提供帮助请给予支持(关注、点赞、分享)项目地址https://gitcode.com/gh_mirrors/code/CodeGuide点击查看免费下载相关推荐Lottery 抽奖系统实战使用 Kafka MQ 解耦抽奖与发货流程Lottery 抽奖系统实战使用 Kafka MQ 解耦抽奖与发货流程 导读 本篇基于《Lottery 分布式抽奖系统》Part 2 第 16 节的核心内容文档教程后端在 Lottery 抽奖系统中引入 XXL-JOB分布式任务调度处理活动状态扫描在 Lottery 抽奖系统中引入 XXL JOB分布式任务调度处理活动状态扫描 本文以 Lottery 分布式抽奖系统DDD 四层架构为背景讲解如何在文档教程后端FlowMVI未来路线图即将推出的功能和社区发展计划FlowMVI未来路线图即将推出的功能和社区发展计划 FlowMVI 作为Kotlin Multiplatform的现代化架构框架正在快速演进中。这个强大的跨平台移动开发状态管理插件系统创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表