当前位置: 首页 > article >正文

《RocketMQ实战与进阶》08 结合实际场景顺序消费、消息过滤实战

顺序消费业务场景描述现在开发一个银行类项目对用户的每一笔余额变更都需要发送短信通知到用户。如果用户同时在电商平台下单转账两个渠道在同一时间进行了余额变更此时用户收到的短信必须顺序的例如先网上购物消费了 128余额 1000再转账给朋友 200剩余余额 800如果这两条短信的发送顺序颠倒给用户会带来很大的困扰故在该场景下必须保证顺序。这里所谓的顺序是针对同一个账号的不同的账号无需保证顺序性例如用户 A 的余额发送变更用户 B 的余额发生变更这两条短信的发送其实相互不干扰的故不同账号之间无需保证顺序。代码实现本篇代码主要采用截图的方式展示其关键代码并对其进行一些简单的解读。首先这里的主业务是操作账户的余额然后是余额变更后需要发短信通知给用户但由于发送短信与账户转载是两个相对独立但又紧密的操作故这里可以引入消息中间件来解耦这两个操作。但由于发送短信业务其顺序一定要与扣款的顺序保证一致故需要使用顺序消费。由于 RocketMQ 只提供了消息队列的局部有序故如果要实现某一类消息的顺序执行就必须将这类消息发送到同一个队列故这里在消息发送时使用了 MessageQueueSelector并且使用用户账户进行队列负载这样同一个账户的消息就会账号余额变更的顺序到达队列然后队列中的消息就能被顺序消费。顺序消费的事件监听器为 MessageListenerOrderly表示顺序消费。顺序消费在使用上比较简单那 RocketMQ 顺序消费是如何实现的队列重新负载时还能保持顺序消费吗顺序消费会重复消费吗RocketMQ 顺序消费原理简述在 RocketMQ 中PUSH 模式的消息拉取模型如下图所示上述流程在前面的章节中已做了详述这里不再累述这里想重点突出线程池。RocketMQ 消息消费端按照消费组进行的线程隔离即每一个消费组都会创建已线程池由一个线程池负责分配的所有队列中的消息。**所以要保证消费端对单队列中的消息顺序处理故多线程处理需要按照消息消费队列进行加锁。**故顺序消费在消费端的并发度并不取决消费端线程池的大小而是取决于分给给消费者的队列数量故如果一个 Topic 是用在顺序消费场景中建议消费者的队列数设置增多可以适当为非顺序消费的 2~3 倍这样有利于提高消费端的并发度方便横向扩容。消费端的横向扩容或 Broker 端队列个数的变更都会触发消息消费队列的重新负载在并发消息时在队列负载的时候一个消费队列有可能被多个消费者同时消息但顺序消费时并不会出现这种情况因为顺序消息不仅仅在消费消息时会锁定消息消费队列在分配到消息队列时能从该队列拉取消息还需要在 Broker 端申请该消费队列的锁即同一个时间只有一个消费者能拉取该队列中的消息确保顺序消费的语义。从前面的文章中也介绍到并发消费模式在消费失败是有重试机制默认重试 16 次而且重试时是先将消息发送到 Broker然后再次拉取到消息这种机制就会丧失其消费的顺序性故如果是顺序消费模式消息重试时在消费端不停的重试重试次数为 Integer.MAX_VALUE即如果一条消息如果一直不能消费成功其消息消费进度就会一直无法向前推进即会造成消息积压现象。温馨提示顺序消息时一定要捕捉异常必须能区分是系统异常还是业务异常更加准确的要能区分哪些异常是通过重试能恢复的哪些是通过重试无法恢复的。无法恢复的一定要尽量在发送到 MQ 之前就要拦截并且需要提高告警功能。消息过滤实战业务场景描述例如公司采用的是微服务架构分为如下几个子系统基础数据、订单模块、商家模块各个模块的数据库都是独立的。微服务带来的架构伸缩性不容质疑但数据库的相互独立对于基础数据的 join 操作就不那么方便了即在订单模块需要使用基础数据还需要通过 Dubbo 服务的方式去请求接口为了避免接口的调用基础数据的数据量又不是特别多的情况项目组更倾向于将基础数据的数据同步到各个业务模块的数据库然后基础数据发生变化及时通知订单模块这样与基础数据的表 join 操作就可以在本库完成。技术方案上述方案的关键思路基础数据一旦数据发生变化就向 MQ 的 base_data_topic 发送一条消息。下游系统例如订单模块、商家模块订阅 base_data_topic 完成数据的同步。问题如果订单模块出现一些不可预知的错误导致数据同步出现异常并且发现的时候存储在 MQ 中的消息已经被删除此时需要上游基础数据重推数据这个时候如果基础数据重推的消息直接发送到 base_data_topic那该 Topic 的所有消费者都会消费到这显然是不合适的。怎么解决呢通常有两种办法为各个子模块创建另外一个主题例如 retry_ods_base_data_topic这样需要向哪个子系统就向哪个 Topic 发送。引入 Tag 机制。本节主要来介绍一下 Tag 的思路。首先正常情况下基础模块将数据变更发送到 base_data_topic并且消息的 Tag 为 all。然后为每一个子系统定义一个单独的重推 Tag例如 ods、shop。消费端同时订阅 all 和各自的重推 Tag完美解决问题。代码实现在消息发送时需要按照需求指定消息的 Tag其示例代码如下然后在消息消费时订阅时更加各自的模块订阅各自关注的 Tag其示例代码如下在消息订阅时一个消费组可以订阅多个 Tag多个 Tag 使用双竖线分隔。Topic 与 Tag 之争用 Tag 对同一个主题进行区分会引来一个“副作用”就是在重置消息消费位点时该消费组需要“处理”的是所有标签的数据虽然在 Broker 端、消息消费端最终会过滤不符合 Tag 的消息并不会执行业务逻辑但在消息拉取时还是需要将消息读取到 PageCache 中并进行过滤会有一定的性能损耗但这个不是什么大问题。在数据推送这个场景除了使用 Tag 机制来区分重推数据外也可以为重推的数据再申请一个额外的主题即通过主题来区分不同的数据这种方案倒不说不可以但这个在运维管理层面需要申请众多的 Topic而这类 Topic 存储的其实是一类数据使用不同的 Topic 存储同类数据会显得较为松散。当然如果是不同的业务场景就建议使用 Topic 来隔离。小结本篇主要从两个贴近实战场景结合场景来介绍如何使用顺序消息、消息过滤所有的示例代码整合在一个 Spring Boot Dubbo RocketMQ MyBatis 的工程中。

相关文章:

《RocketMQ实战与进阶》08 结合实际场景顺序消费、消息过滤实战

顺序消费 业务场景描述 现在开发一个银行类项目,对用户的每一笔余额变更都需要发送短信通知到用户。如果用户同时在电商平台下单,转账两个渠道在同一时间进行了余额变更,此时用户收到的短信必须顺序的,例如先网上购物,…...

海思ISP实战:从sensor标定到图像优化的完整流程解析

海思ISP全流程实战:从硬件标定到算法调优的深度指南 在嵌入式视觉系统的开发中,图像信号处理(ISP)流水线的质量直接决定了最终成像效果。作为国产芯片的代表,海思系列SoC的ISP模块凭借其高度可定制性和出色的性能表现…...

保姆级教程:用宝塔面板+EMQX Cloud,零服务器搭建物联网数据中台(MQTT到MySQL)

零服务器架构实战:基于EMQX Cloud与宝塔面板的物联网数据中台搭建指南 物联网技术的普及让数据采集与分析变得触手可及,但对于资源有限的个人开发者或初创团队来说,传统服务器架构的高成本和运维复杂度仍是难以跨越的门槛。本文将介绍一种无需…...

终极指南:如何用EverythingToolbar实现Windows文件搜索效率翻倍 [特殊字符]

终极指南:如何用EverythingToolbar实现Windows文件搜索效率翻倍 🚀 【免费下载链接】EverythingToolbar Everything integration for the Windows taskbar. 项目地址: https://gitcode.com/gh_mirrors/eve/EverythingToolbar 你是否厌倦了在Windo…...

告别.bat文件!用更稳定的环境变量法配置Abaqus2019子程序开发环境(VS2019+Intel Fortran)

永久环境变量配置:Abaqus2019子程序开发环境的高效搭建指南 在Abaqus子程序开发中,传统的.bat脚本配置方式虽然简单直接,但存在路径依赖性强、容易失效等问题。本文将介绍一种基于系统环境变量的配置方法,通过永久性设置VS2019与I…...

德州扑克GTO求解器Desktop Postflop:如何用开源工具提升你的扑克决策水平

德州扑克GTO求解器Desktop Postflop:如何用开源工具提升你的扑克决策水平 【免费下载链接】desktop-postflop [Development suspended] Advanced open-source Texas Holdem GTO solver with optimized performance 项目地址: https://gitcode.com/gh_mirrors/de/d…...

OAK-D vs OAK-D-Lite怎么选?从项目需求出发,聊聊我的选购心得和避坑指南

OAK-D vs OAK-D-Lite实战选型指南:从参数表到真实项目落地的深度解析 当你在机器人导航系统中需要精准的深度感知,或在AR/VR项目中追求轻量化的3D视觉方案时,OAK-D和OAK-D-Lite这两款明星产品总会同时出现在选购清单上。作为深度参与过仓储机…...

鸿蒙 Electron 跨平台应用开发:文字战斗系统与英雄系统进阶开发详解——自定义英雄参战

欢迎加入开源鸿蒙PC社区: https://harmonypc.csdn.net/ atomgit开源仓库地址: https://atomgit.com/feng8403000/electron_TextGame_DIVBOSS 示例效果 项目背景 在游戏开发中,玩家对游戏的定制化需求越来越高。为了满足玩家的个性化需求&am…...

Seaborn的sns.load_dataset()不灵了?别急,这里有本地化数据集的终极解决方案(附GitHub仓库地址)

Seaborn数据集本地化实战:解决sns.load_dataset()访问难题的完整指南 当你兴致勃勃地打开Jupyter Notebook准备复现Seaborn的示例代码时,突然遭遇ConnectionError或HTTPError——这可能是数据科学工作者最熟悉的挫败感之一。本文将彻底解决这个看似简单…...

Phi-3.5-mini-instruct部署教程:WSL2环境下Windows本地运行vLLM+Chainlit全步骤

Phi-3.5-mini-instruct部署教程:WSL2环境下Windows本地运行vLLMChainlit全步骤 1. 环境准备与快速部署 在开始之前,请确保你的Windows系统已启用WSL2并安装了Ubuntu发行版。本教程将指导你完成从零开始的完整部署流程。 1.1 系统要求 Windows 10/11 …...

GeoAI通用平台:基于LangChain的智能地理空间AI架构实践

引言 在当今数据驱动的时代,地理空间分析在各个行业中变得越来越重要。然而,传统的GIS工具通常需要专业知识和复杂的工作流程,这对许多用户来说是一个门槛。GeoAI通用平台通过将大语言模型(LLM)与地理空间数据处理相结合,实现了自然语言与地理信息系统的交互,有效解决了…...

保姆级教程:绕过Windows 11 PIN锁,利用‘轻松使用’图标和msconfig恢复系统正常启动

Windows系统启动异常修复:从原理到实战的深度解析 当Windows系统启动遇到问题时,许多用户会感到手足无措。本文将深入探讨Windows启动机制,并提供一个系统化的解决方案框架,帮助技术爱好者不仅解决问题,更能理解背后的…...

Debian 11上Qt程序中文输入失效?手把手教你编译fcitx5-qt插件(Qt6/Qt5通用)

Debian 11上Qt程序中文输入失效的终极解决方案:从原理到实践 刚在Debian 11上完成Qt应用的开发,却发现无法通过fcitx输入中文?这可能是Linux桌面开发中最令人抓狂的问题之一。作为开发者,我们期望的是流畅的编码体验,而…...

树莓派Zero 2 W打造超低功耗家庭媒体服务器实战

1. 项目概述:打造一台超低功耗的Mini-PI媒体服务器去年冬天,当我发现家里的老款NAS在同时处理文件共享和视频转码时功耗高达35W,电费账单上的数字让我下定决心寻找更节能的解决方案。经过多次尝试,最终基于树莓派Zero 2 W搭建的这…...

Alpha AI 量化 vs 传统量化深度对比测评

在数字经济的演进中,量化技术一直处于鄙视链的顶端。但随着 AI 大模型与 Web3 技术的爆发,传统的量化架构正面临前所未有的挑战。近期备受瞩目的Alpha AI平台,打出了“极简智能”的旗号。它究竟是对传统工具的简单升级,还是一次彻…...

手把手调试RK3588电源:当CPU变频失效时,如何排查DTS中的PMIC配置问题

RK3588电源调试实战:当DVFS失效时如何精准定位PMIC初始化问题 凌晨三点,实验室的咖啡机已经空了第三轮。盯着屏幕上/d/opp/opp_summary里空空如也的频率信息,我意识到这又是一个典型的RK3588电源初始化顺序问题。作为嵌入式工程师&#xff0c…...

亚马逊至多330亿美元追加投资Anthropic,十年合作超千亿美元剑指AI大模型

亚马逊330亿美元投资Anthropic,十年合作超千亿4月21日,亚马逊宣布向美国AI大模型独角兽Anthropic投资50亿美元(约合人民币341亿元),未来还将根据商业里程碑情况追加至多200亿美元(约合人民币1364亿元&#…...

Agent-Ready ≠ 自动就绪!Spring Boot 4.0插件必须满足的4项JVM兼容性阈值(含OpenJDK 21+ GraalVM 24.1实测数据)

第一章:Spring Boot 4.0 Agent-Ready 架构概述Spring Boot 4.0 引入了原生支持 Java Agent 的“Agent-Ready”架构设计,标志着运行时可观测性、动态字节码增强与无侵入式监控能力的深度集成。该架构不再将 Agent 视为外部附加组件,而是通过标…...

镜像体积压缩78%、冷启提速4.2倍,Docker边缘轻量化部署实战指南,

第一章:Docker边缘部署优化概述在资源受限、网络不稳定、物理环境多变的边缘计算场景中,Docker 容器虽具备轻量与可移植优势,但默认配置常导致启动延迟高、镜像体积大、内存占用冗余及运行时不可靠等问题。边缘设备(如工业网关、车…...

Docker 27资源监控增强配置:3分钟定位CPU爆表、内存泄漏与网络抖动的7个隐藏参数

第一章:Docker 27资源监控增强配置全景概览Docker 27 引入了多项面向生产环境的资源监控增强能力,涵盖 CPU、内存、I/O、网络及自定义指标采集等维度。这些增强并非孤立功能,而是通过统一的 docker stats 接口、可插拔的监控后端集成&#xf…...

Java传统阻塞IO项目转Loom响应式,这4类代码必须重写——含AST自动化改造脚本

第一章:Java传统阻塞IO项目转Loom响应式编程转型全景图Java平台自JDK 21起正式将虚拟线程(Virtual Threads)作为标准特性引入,标志着Loom项目从孵化走向生产就绪。这一演进并非简单替换线程模型,而是重构整个高并发应用…...

Dify API并发限流突然触发?揭秘rate_limit字段的隐藏单位陷阱与burst窗口算法反直觉行为(附压测对比数据)

第一章:Dify API并发限流突然触发?揭秘rate_limit字段的隐藏单位陷阱与burst窗口算法反直觉行为(附压测对比数据)rate_limit字段的真实单位是“每秒请求数”,而非“每分钟”或“总配额” Dify API文档中未明确说明rate…...

开箱即用!ComfyUI Qwen人脸生成图像,无需代码一键生成

开箱即用!ComfyUI Qwen人脸生成图像,无需代码一键生成 1. 模型简介与核心能力 Qwen-Image-Edit-F2P人脸生成图像模型是一款基于ComfyUI部署的AI工具,它能将单张人脸照片转化为风格多样的全身人像。这个模型特别适合需要快速生成人物形象但缺…...

Qt程序里调用Shell脚本,用QProcess还是system?一个ROS开发者的踩坑实录

Qt中调用Shell脚本的终极指南:QProcess与system的深度对比与实战避坑 在机器人操作系统(ROS)开发中,我们经常需要在Qt开发的图形界面中集成各种命令行工具和脚本。无论是启动一个ROS节点,还是执行复杂的环境配置脚本,如何在Qt应用…...

大模型微调面试100问,非常详细收藏我这一篇就好了!

本文系统梳理了LoRA权重更新梯度反向传播公式推导,解释了固定只训练和能显著减少显存占用的原因。深入解析了QLoRA中NF4量化原理及其利用高斯分布优化量化区间的机制。详细阐述了Double Quantization在QLoRA中的实现步骤及其显存节省效果。推导了DPO损失函数从RLHF目…...

AI Agent智能体时代来临:Skills技能与Harness框架如何协同打造超级AI?

本文深入探讨了AI Agent智能体、Skills技能和Harness框架三者之间的关系及应用。AI Agent作为具备自主能力的AI执行主体,通过Skills技能模块实现专项任务执行,并由Harness框架进行统筹调度与安全管控。三者协同构成了可落地的AI智能体系统,典…...

Jellyfin元数据插件MetaShark终极指南:快速为你的媒体库添加中文电影信息

Jellyfin元数据插件MetaShark终极指南:快速为你的媒体库添加中文电影信息 【免费下载链接】jellyfin-plugin-metashark jellyfin电影元数据插件 项目地址: https://gitcode.com/gh_mirrors/je/jellyfin-plugin-metashark 还在为Jellyfin媒体库中那些只有英文…...

从BERT到ViT:聊聊那个“借”来的CLS Token,以及我们真的需要它吗?

从BERT到ViT:聊聊那个“借”来的CLS Token,以及我们真的需要它吗? 在计算机视觉领域,Vision Transformer(ViT)的出现彻底改变了传统CNN主导的格局。而其中最具争议的设计之一,莫过于那个从NLP领…...

MacBook M1/M2芯片上,用Python 3.10手动安装PyTorch全家桶的保姆级避坑指南

MacBook M1/M2芯片Python 3.10环境配置:PyTorch全家桶精准安装实战手册 当你在M1/M2芯片的MacBook上打开终端,输入那行看似简单的pip install torch命令时,系统报错的那一刻,可能就开启了一场令人头疼的依赖关系迷宫之旅。作为深…...

别RAG了,直接导航:企业知识库Skill上线~

RAG的"结构性盲区" 传统RAG把大模型当成检索结果的被动消费者——它只能看到被硬塞进来的Top-k片段,既不了解语料库的全貌,也不知道自己错过了什么。面对"如何将独资企业转为LLC"这类跨主题复杂查询,平面检索只能返回表…...