RocketMQ半消息对消费者不可见是如何实现的?——事务消息机制揭秘
首发于工号【BiggerBoy】,原文链接
——“半消息藏在这里,但为什么你偷看也没用?”
上篇《RocketMQ系列笔记(三):消息模型与高阶玩法,顺序事务消息拿捏指南》中提到“TBW102是RocketMQ预留的事务消息Topic”,是什么意思?为什么消费者看不到半消息?是如何实现的?带着这些疑问,开启今天的探索之旅!
这句话隐藏的意思就是:生产者发送事务消息时实际Broker会把半消息存储到TBW102这个Topic。当生产者通知Broker提交时,Broker会将消息发送到生产者指定的Topic,此时消费者才能消费该消息。
以下是更详细的流程说明:
事务消息:一手交钱一手交货
再来回顾一下事务消息的流程:
发送半消息
- 生产者发送事务消息时,首先将消息作为半消息发送到Broker
- 这个半消息会被存储在RocketMQ的默认事务Topic
TBW102中 - 此时,消息对消费者是不可见的,因为它还没有被正式提交
执行本地事务
- 半消息提交成功后,生产者执行本地事务逻辑(例如数据库操作)
- 本地事务的执行结果(成功或失败)决定了后续的操作
通知Broker提交或回滚
- 提交如果本地事务成功,生产者会通知Broker提交半消息。此时,Broker会将消息从
TBW102移动到生产者指定的目标Topic,消息对消费者可见 - 回滚如果本地事务失败,生产者会通知Broker回滚半消息。此时,Broker会丢弃 TBW102 中的半消息,消息不会被发送到目标Topic
事务消息的奥秘
消息可见性
- 半消息阶段消息存储在
TBW102,对消费者不可见 - 提交后消息移动到目标Topic,对消费者可见
为什么设计为不可见?
- 事务消息的核心设计
- RocketMQ的事务消息机制是为了保证消息的最终一致性
- 在半消息阶段,消息对消费者不可见,是为了避免消费者处理到未确认的消息(可能导致数据不一致)
- 只有在生产者明确提交事务后,消息才会被移动到目标Topic,对消费者可见
简单来说:
TBW102里的消息就像“加密文件”,只有事务完成后才会被“解密”到正确的位置。
配置
- 自定义半消息Topic可通过配置
transactionTopic参数指定其他Topic - Broker配置在Broker配置文件中设置
transactionTopic参数
注意事项
- 可以自定义通过Broker配置
transactionTopic参数,灵活指定事务消息的存储位置 - 但没必要乱动如果没有特殊需求,直接用默认的
TBW102反而更省心 - 核心原则事务Topic是RocketMQ内部机制,业务代码无需感知,你的重点仍是本地事务和最终消息的一致性
- 避免冲突不要在生产环境中使用
TBW102作为业务Topic,以免冲突 - 监控与维护需监控和维护事务Topic,确保事务消息机制正常运行
总结
- 半消息存储在
TBW102,对消费者不可见 - 提交后消息移动到目标Topic,对消费者可见
- 回滚消息被丢弃,不会发送到目标Topic
这种机制确保了事务消息的原子性,即消息的发送与本地事务的执行结果保持一致。
有的小伙伴就会好奇问了:如果消费者订阅TWB102呢,不就可以消费了吗?刚刚说“生产者通知Broker回滚消息,Broker会丢弃TWB102中的半消息”,这里的丢弃是从Broker中删除吗?不会违背RocketMQ顺序写的特性吗?
这是个好问题!下面来揭秘一下:
消费者订阅 TBW102 的情况
- 理论上可以订阅消费者确实可以订阅
TBW102这个Topic - 实际意义有限
- TBW102是RocketMQ内部用于存储半消息的Topic,这些消息还未被确认提交或回滚
- 即使消费者订阅了
TBW102,也只能看到未完成事务的半消息,这些消息的状态是不确定的(可能最终会被提交或回滚) - 从业务逻辑上来说,消费这些半消息是没有意义的,因为它们可能最终会被丢弃
划重点:
哪怕你订阅了TBW102,看到的也只是“未确认状态”的半消息,它们可能下一秒就被删除或转移,毫无业务价值。
消息被丢弃的含义
- 回滚时的处理
- 当生产者通知Broker回滚事务时,Broker会将
TBW102中对应的半消息标记为已回滚 - 这些消息会被标记为已删除,消费者无法再访问这些消息
- 当生产者通知Broker回滚事务时,Broker会将
实际上被回滚的半消息还存储在Commitlog中,只是被标记为已删除,之所以没有物理删除和RocketMQ的存储机制有一定关系。
RocketMQ的存储机制
- CommitLog:
- RocketMQ将所有消息(包括事务消息)
顺序写入一个统一的文件,称为CommitLog - 这种设计保证了高性能的写入,因为磁盘只需要顺序追加数据
- RocketMQ将所有消息(包括事务消息)
- ConsumeQueue:
- 每个Topic的消息索引存储在
ConsumeQueue中,消费者通过ConsumeQueue快速定位消息
- 每个Topic的消息索引存储在
- 事务消息的特殊性:
- 事务消息(包括半消息)也会写入
CommitLog,但在事务未完成时,不会将消息索引写入目标Topic的ConsumeQueue
- 事务消息(包括半消息)也会写入
消息删除的实现原理
删除操作的本质:RocketMQ的“删除”并不是直接从 CommitLog 中物理擦除数据,而是通过以下方式实现:标记删除:对于回滚的事务消息,RocketMQ会将其标记为“已删除”跳过消费:消费者从ConsumeQueue读取消息时,会跳过被标记为删除的消息物理删除:RocketMQ会定期执行文件清理(默认72小时),将过期的文件(包括已删除的消息)从磁盘中删除顺序写的保持:
- 删除操作不会影响
CommitLog的顺序写特性,因为删除只是标记消息状态,而不是立即修改CommitLog文件 - 物理删除是通过清理整个文件(而不是单独删除某条消息)来实现的,因此不会破坏顺序写的性能
- 删除操作不会影响
结论:
删除操作既不会破坏顺序写,也不会让磁盘“千疮百孔”,RocketMQ早就想好了怎么优雅“扔垃圾”。
总结
- 半消息 存储在
TBW102,对消费者不可见。 - 提交后 消息移动到目标Topic,对消费者可见。
- 回滚 消息被丢弃,不会发送到目标Topic。
因此,RocketMQ的事务消息机制通过 TBW102 和半消息的设计,确保了消息的可靠性和一致性,避免了消费者处理到未确认的消息。
好了,今天的分享就到这里啦!如果对你有帮助,辛苦转发关注,感谢支持~
RocketMQ半消息对消费者不可见是如何实现的?——事务消息机制揭秘的更多相关文章
- 消息队列之事务消息,RocketMQ 和 Kafka 是如何做的?
每个时代,都不会亏待会学习的人. 大家好,我是 yes. 今天我们来谈一谈消息队列的事务消息,一说起事务相信大家都不陌生,脑海里蹦出来的就是 ACID. 通常我们理解的事务就是为了一些更新操作要么都成 ...
- RocketMQ源码详解 | Broker篇 · 其四:事务消息、批量消息、延迟消息
概述 在上文中,我们讨论了消费者对于消息拉取的实现,对于 RocketMQ 这个黑盒的心脏部分,我们顺着消息的发送流程已经将其剖析了大半部分.本章我们不妨乘胜追击,接着讨论各种不同的消息的原理与实现. ...
- RocketMQ实现事务消息
在RocketMQ4.3.0版本后,开放了事务消息这一特性,对于分布式事务而言,最常说的还是二阶段提交协议,那么RocketMQ的事务消息又是怎么一回事呢,这里主要带着以下几个问题来探究一下Rocke ...
- RocketMQ源码分析之从官方示例窥探:RocketMQ事务消息实现基本思想
摘要: RocketMQ源码分析之从官方示例窥探RocketMQ事务消息实现基本思想. 在阅读本文前,若您对RocketMQ技术感兴趣,请加入RocketMQ技术交流群 RocketMQ4.3.0版本 ...
- 可靠消息最终一致性【本地消息表、RocketMQ 事务消息方案】
更多内容,前往IT-BLOG 一.可靠消息最终一致性事务概述 可靠消息最终一致性方案是指当事务发起方执行完成本地事务后并发出一条消息,事务参与方(消息消费者)一定能够接收消息并处理事务成功,此方案强调 ...
- RocketMQ支持事务消息机制
事务消费 我们经常支付宝转账余额宝,这是日常生活的一件普通小事,但是我们思考支付宝扣除转账的钱之后,如果系统挂掉怎么办,这时余额宝账户并没有增加相应的金额,数据就会出现不一致状况了. 上述场景在各个类 ...
- Spring Cloud Alibaba学习笔记(11) - RocketMQ事务消息
在Spring中,我们要实现事务,一般通过@Transactional注解实现.这在引入RocketMQ之前没有问题,但是在引入了RocketMQ之后,如果消息发送之后的业务逻辑处理发生了异常的话,这 ...
- RocketMQ入门到入土(二)事务消息&顺序消息
接上一篇:RocketMQ入门到入土(一)新手也能看懂的原理和实战! 一.事务消息的由来 1.案例 引用官方的购物案例: 小明购买一个100元的东西,账户扣款100元的同时需要保证在下游的积分系统给小 ...
- RocketMQ事务消息实现分析
这周RocketMQ发布了4.3.0版本,New Feature中最受关注的一点就是支持了事务消息: 今天花了点时间看了下具体的实现内容,下面是简单的总结. RocketMQ事务消息概要 通过冯嘉发布 ...
- RocketMQ事务消息回查设计方案
用户U1从A银行系统转账给B银行系统的用户U2的处理过程如下:第一步:A银行系统生成一条转账消息,以事务消息的方式写入RocketMQ,此时B银行系统不可见这条消息(Prepare阶段) 第二步:写入 ...
随机推荐
- DeepSeek处理自有业务的案例:让AI给你写一份小众编辑器(EverEdit)的语法着色文件
1 DeepSeek处理自有业务的案例:让AI给你写一份小众编辑器(EverEdit)的语法着色文件 1.1 背景 AI能力再强,如果不能在企业的自有业务上产生助益,那基本也是一无是处.将企业的自 ...
- ATT&CK实战系列(一)
环境下载 下载靶场环境,并导入虚拟机分别是win2003.win7.winserver2008 配置网络 虚拟机--编辑--虚拟机网络编辑器--添加网络VMnet2--仅主机模式分配的地址是192.1 ...
- Flink学习(十六) ProcessFunctionAPI(底层API)
我们之前学习的转换算子是无法访问时间的时间戳信息和水位线信息的.而这些在一些应用场景下,极为重要,例如MapFunction这样的map转换算子就无法访问时间戳或者当前事件的事件时间. 基于此,Dat ...
- Spring Boot创建完项目运行Cannot determine embedded database driver class for database type NONE
spring boot 创建项目引用mybatis后,直接运行会提示: Cannot determine embedded database driver class for database typ ...
- 【由技及道】螺蛳壳里做道场-git仓库篇-gitlab-Vs-gitea【人工智障AI2077的开发日志001】
指令接收:「开始构建代码宇宙」 系统检测:需求模糊度99.9% 启动应急协议:构建最小可行性生态圈 核心组件锁定:代码基因库(人类称之为Git仓库) 需求分析:论人类语言的艺术性 人类指令翻译机 表面 ...
- C#/.NET/.NET Core优秀项目和框架2025年2月简报
前言 公众号每月定期推广和分享的C#/.NET/.NET Core优秀项目和框架(每周至少会推荐两个优秀的项目和框架当然节假日除外),公众号推文中有项目和框架的详细介绍.功能特点.使用方式以及部分功能 ...
- Linux下yum安装mysql 遇到的问题Can't open and lock privilege tables: Table 'mysql.user' doesn't exist 错误
今天在linux下安装mysql时 执行service mysqld start时, mysql总是启动失败 后来查看mysql日志:/var/log/mysqld.log,发现有个Can't ope ...
- Window10永久暂停(禁用)自动更新
终于彻底设置window10不自动更新了(禁用自动更新) 设置成功后的标识 设置成功后,重启电脑再打开就会显示这样的,这个才是禁用成功的标识: 之前安装了window 10 ,但是window 10 ...
- ERROR: Unexpected bus error encountered in worker. This might be caused by insufficient shared memory (shm).
报错 ERROR: Unexpected bus error encountered in worker. This might be caused by insufficient shared me ...
- 算法分析-回溯算法-求解N皇后问题
一.题目需求 n皇后问题是一道比较经典的算法题.它研究的是将n个皇后放置在一个n×n的棋盘上,使皇后彼此之间不相互攻击. 即任意两个皇后都不能处于同一行.同一列或同一斜线上. 二.算法思想 1.构建棋 ...