RocketMQ之四:RocketMq事务消息
事务消息
通过消息的异步事务,可以保证本地事务和消息发送同时执行成功或失败,从而保证了数据的最终一致性。
发送端执行如下几步:
- 发送prepare消息,该消息对Consumer不可见
- 执行本地事务(如 update DB)
- 若本地事务执行成功,则向MQ提交消息确认发送指令;若本地事务执行失败,则向MQ发送取消指令(取消prepared消息)
若MQ长时间未收到确认发送或取消发送的指令,则向业务系统询问本地事务状态,并做补偿处理。(
RocketMQ第一阶段发送
Prepared消息
时,会拿到消息的地址,第二阶段执行本地事物,第三阶段通过第一阶段拿到的地址去访问消息,并修改状态。细心的你可能又发现问题了,如果确认消息发送失败了怎么办?RocketMQ会定期扫描消息集群中的事物消息,这时候发现了Prepared消息
,它会向消息发送者确认,Bob的钱到底是减了还是没减呢?如果减了是回滚还是继续发送确认消息呢?RocketMQ会根据发送端设置的策略来决定是回滚还是继续发送确认消息。这样就保证了消息发送与本地事务同时成功或同时失败。如果
endTransaction
方法执行失败,导致数据没有发送到broker
,broker
会有回查线程定时(默认1分钟)扫描每个存储事务状态的表格文件,如果是已经提交或者回滚的消息直接跳过,如果是prepared状态
则会向Producer
发起CheckTransaction
请求,Producer
会调用DefaultMQProducerImpl.checkTransactionState()
方法来处理broker
的定时回调请求,而checkTransactionState
会调用我们的事务设置的决断方法,最后调用endTransactionOneway
让broker
来更新消息的最终状态。)
RocketMq事务消息
客户端事务消息发送
发送prepare消息复用了普通消息发送,只是给消息增加了TRAN_MSG=true的属性,该属性决定prepare消息对Consumer不可见
消息写入CommitLog
事务消息的CommitLog写入和普通消息一致,它利用文件的顺序写来提升吞吐量,并采用文件映射的方式降低系统开销。
消息写入ConsumeQueue
ConsumeQueue的写入是采用异步方式完成的,ReputMessageSerivce作为一个长驻线程负责查询索引的构造和ConsumeQueue的写入,对于Prepare/Rollback消息不会写ConsumeQueue,从而保证它们对Consumer不可见
Broker端事务提交/回滚
Broker收到提交/回滚指令后,首先从根据offset从CommitLog读出原有的prepare消息,构造新的消息(修改事务状态标识)并写入Broker。对于一条事务消息,RocketMq会存储两条消息,存在一定资源浪费。其实它是为了保证随后的消费者能尽可能从PageCache中读到该消息,而不是读取较早的prepare消息(可能导致缺页中断),以提升系统吞吐量。
此外,rocketmq的最新版本(4.2.0)尚未支持本地事务的状态回查,这样可能存在由于网络抖动,导致commit/rollback未提交到broker导致prepare消息长期悬挂的风险。
在RocketMq的设计文档中,为事务消息增加了一张事务状态表,它维护了消息的Offset、事务状态(P/C/R)信息。可以采用如下思路实现事务消息的回查机制:
- 在prepare消息写入commitLog后,可以通过CommitLogDispatcher写入一条事务状态记录(state=P)
- 在提交/回滚事务时,根据transactionId找到对应的事务状态记录,并修改对应的事务状态
- 通过长驻线程扫描事务状态表,对于超过一定时间的Prepare事务,发起对业务方的事务状态回查,根据回查结果修改事务状态,并向brokder发送相应的Commit/Rollback消息。
作者:Andy的书斋
链接:https://www.jianshu.com/p/c26b3af5880f
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
RocketMQ之四:RocketMq事务消息的更多相关文章
- RocketMQ学习笔记(10)----RocketMQ的Producer 事务消息使用
1. 事务消息原理图 RocketMQ除了支持普通消息,顺序消息之外,还支持了事务消息. 1. 什么是分布式事务? 分布式事务就是指事务的参与者.支持事务的服务器.资源服务器以及事务管理器分别位于不同 ...
- RocketMQ与MYSQL事务消息整合
1.基础理论知识篇“两阶段提交”如果你了解可以跳过这段,当然如果你想深入了解你可以购买相关书籍或去搜索相关资料阅读 两阶段提交分为 正常提交和异常提交或异常回滚 上面是正常提交的示意图,协调者发起预提 ...
- 分布式开放消息系统RocketMQ的原理与实践(消息的顺序问题、重复问题、可靠消息/事务消息)
备注:1.如果您此前未接触过RocketMQ,请先阅读附录部分,以便了解RocketMQ的整体架构和相关术语2.文中的MQServer与Broker表示同一概念 分布式消息系统作为实现分布式系统可扩展 ...
- rocketmq事务消息
rocketmq事务消息 参考: https://blog.csdn.net/u011686226/article/details/78106215 https://yq.aliyun.com/art ...
- 搞懂分布式技术19:使用RocketMQ事务消息解决分布式事务
搞懂分布式技术19:使用RocketMQ事务消息解决分布式事务 初步认识RocketMQ的核心模块 rocketmq模块 rocketmq-broker:接受生产者发来的消息并存储(通过调用rocke ...
- RocketMQ源码分析之RocketMQ事务消息实现原下篇(事务提交或回滚)
摘要: 事务消息提交或回滚的实现原理就是根据commitlogOffset找到消息,如果是提交动作,就恢复原消息的主题与队列,再次存入commitlog文件进而转到消息消费队列,供消费者消费,然后将原 ...
- RocketMQ源码详解 | Broker篇 · 其四:事务消息、批量消息、延迟消息
概述 在上文中,我们讨论了消费者对于消息拉取的实现,对于 RocketMQ 这个黑盒的心脏部分,我们顺着消息的发送流程已经将其剖析了大半部分.本章我们不妨乘胜追击,接着讨论各种不同的消息的原理与实现. ...
- RocketMQ源码 — 十一、 RocketMQ事务消息
分布式事务是一个复杂的问题,rmq实现了事务的最终一致性,rmq保证本地事务成功消息一定会发送成功并被成功消费,如果本地事务失败了,消息不会被发送. rmq事务消息的实现过程为: producer发送 ...
- 分布式事务之如何基于RocketMQ的事务消息特性实现分布式系统的最终一致性?
导读 在之前的文章中我们介绍了如何基于RocketMQ搭建生产级消息集群,以及2PC.3PC和TCC等与分布式事务相关的基本概念(没有读过的读者详见
随机推荐
- iotop命令详解
iotop是top和iostat程序的混合体,能够显示系统中所有运行进程并将进程根据I/O统计信息排序. 这个软件使用了Linux内核的一些新特性,所以需要2.6.20或者更新的内核. 一般默认情况下 ...
- UUID值
生成这种值:b28043c8-fdb7-4c9e-8df5-b869d38f829d
- mybatis注解大全
注解 目标 相对应的 XML 描述 @CacheNamespace 类 <cache> 为给定的命名空间 (比如类) 配置缓存. 属性:implemetation,eviction, fl ...
- selenium+pyquery爬取淘宝商品信息
import re from selenium import webdriver from selenium.common.exceptions import TimeoutException fro ...
- 【转载】Dijkstra算法和Floyd算法的正确性证明
说明: 本文仅提供关于两个算法的正确性的证明,不涉及对算法的过程描述和实现细节 本人算法菜鸟一枚,提供的证明仅是自己的思路,不保证正确,仅供参考,若有错误,欢迎拍砖指正 ----------- ...
- node中的http内置模块
Node.js开发的目的就是为了用JavaScript编写Web服务器程序.因为JavaScript实际上已经统治了浏览器端的脚本,其优势就是有世界上数量最多的前端开发人员.如果已经掌握了JavaSc ...
- cropbox.js 头像裁剪插件
cropbox.js 一个轻量级和简单的JavaScript,Jquery,YUI插件来裁剪您的头像. 特征 支持dataUrl显示图像(函数getDataURL) 支持Blob上传图片(函数getB ...
- [python]有中文字符程序异常的解决方案
一. 含有中文字符无法运行 在python3中用的是Unicode编码,Unicode号称万国码,可以向所有的编码进行兼容.不会出现这种问题. Python2中使用的是ASCII编码,会出现这种问题. ...
- codeforces#1183H. Subsequences(字符串dp)
题目链接: http://codeforces.com/contest/1183/problem/H 题意: 给出一个长度为$n$的字符串,得到$k$个子串,子串$s$的花费是$n-|s|$ 计算最小 ...
- JAVA NIO缓冲区(Buffer)------ByteBuffer常用方法
参考:https://blog.csdn.net/xialong_927/article/details/81044759 缓冲区(Buffer)就是在内存中预留指定大小的存储空间用来对输入/输出(I ...