RocketMQ - 如何实现事务消息

RocketMq事务消息(分布式事务解决方案) 从问题出发 阅读本文后,我们将了解以上两个问题的答案。 1、RocketMq生产者组(producer group)的设定有什么用? 2、一个订单处理的场景,消费者订阅了订单topic,但总担心丢消息。于是为了防止丢消息,每天都会通过定时任务做一致性校验,这是最佳方案吗? 这还得从基于消息队列实现实现分布式事务的解决方案说起。 常见的分布式事务包括 2PC、3PC、TCC、本地消息表、消息事务、最大努力通知。 今天我们主要讲讲本地消息表、消息事务两种方案。 本地消息表 本地消息表的大致流程是这样的。 pub 阅读详情

事务消息的使用场景

事务消息的使用场景很多,比如在电商系统中用户下单后新增了订单记录,对应的商品库存需要减少。怎么保证新增订单后商品库存减少呢?又例如红包业务,张三给李四发红包,张三的账户余额需要扣减,李四的账户余额需要增加,怎么保证张三账户扣减李四账户加钱呢?

这些问题都是事务问题,可以简单理解为:一个表的数据更新后,如何保证另外一个表的数据也更新成功。如果使用同一个数据库实例,那么问题很简单,可以使用本地事务来解决,Spring的@Transactional注解就支持。

但实际场景并不这么简单,互联网应用的流量大,系统规模通常也比较大,会存在许多数据库实例、分库分表等。我们需要修改的表往往不在同一个数据库实例或者同一个数据库中,此时就不能使用本地事务来解决了,需要用到分布式事务。RocketMQ的一大特点就是支持事务消息,支持一些分布式事务场景。

如何发送事务消息

我们使用RocketMQ事务消息来模拟下单减库存的场景,代码仅包含核心功能代码

  1. 发送订单的事务消息,预提交
@RestController
public class TransactionalController {

    @Autowired
    private Source source;

    public String transactional() {
        Order order = new Order("123", "test");
        String transactionId = UUID.randomUUID().toString();
        MessageBuilder builder = MessageBuilder.withPayload(order).setHeader(RocketMQHeaders.TRANSACTION_ID, transactionId);
        Message message = builder.build();
        source.output().send(message);
        return "OK";
    }
}
server.port=8081
spring.cloud.stream.rocketmq.binder.name-server=192.168.0.118:9876
spring.cloud.stream.bindings.output.destination=TopicTest
spring.cloud.stream.rocketmq.bindings.output.producer.group=demo-group

Order对象保存了订单信息,随机生成一个ID作为消息的事务ID。此时消息已经发送到Broker中,但还未投递出去,Consumer暂时还不能消费这条消息。
2. 执行订单信息入库的事务操作,提交或回滚事务消息

@RocketMQTransactionListener(txProducerGroup = "OrderTransactionGroup")
public class TransactionalMsgListener implements RocketMQLocalTransactionListener {
    @Override
    public RocketMQLocalTransactionState executeLocalTransaction(Message message, Object o) {
        try {
            // 获取前面生成的事务ID
            String transactionId = (String) message.getHeaders().get(RocketMQHeaders.TRANSACTION_ID);
            // 以事务ID为主键,执行本地事务
            Order order = (Order) message.getPayload();
            boolean result = this.saveOrder(order, transactionId);
            return result ? RocketMQLocalTransactionState.COMMIT : RocketMQLocalTransactionState.ROLLBACK;
        } catch (Exception e) {
            return RocketMQLocalTransactionState.ROLLBACK;
        }
    }

    private boolean saveOrder(Order order, String transactionId) {
        // 将事务ID设置为唯一键
        // 调用数据库Insert into 订单表
        return true;
    }

    @Override
    public RocketMQLocalTransactionState checkLocalTransaction(Message message) {
        // 获取事务ID
        String transactionId = (String) message.getHeaders().get(RocketMQHeaders.TRANSACTION_ID);
        // 以事务ID为主键,查询本地事务执行情况
        if (isSuccess(transactionId)) {
            return RocketMQLocalTransactionState.COMMIT;
        }
        return RocketMQLocalTransactionState.ROLLBACK;
    }

    private boolean isSuccess(String transactionId) {
        // 查询数据库 select from 订单表
        return true;
    }
}

实现RocketMQLocalTransactionListener接口,使用@RocketMQTransactionListener注解用于接收本地事务的监听,txProducerGroup是事务组名称,RocketMQLocalTransactionListener接口有两个实现方法:

  • executeLocalTransaction:执行本地事务,在第一步中消息发送成功会回调执行,一旦事务提交成功,下游应用的Consumer能收到该消息,在这里demo的本地事务就是保存订单信息入库
  • checkLocalTransaction:检查本地事务执行状态,如果executeLocalTransaction方法中返回的状态是未知UNKNOWN或者未返回状态,默认会在预处理发送的1分钟后由Broker通知Producer检查本地事务,在Producer中回调本地事务监听器中的checkLocalTransaction方法。检查本地事务时,可以根据事务ID查询本地事务的状态,再返回具体事务状态给Broker。
  1. 消费订单消息
@EnableBinding({Sink.class})
@SpringBootApplication
public class App 
{
    public static void main( String[] args )
    {
        SpringApplication.run(App.class);
    }

    @StreamListener(Sink.INPUT)
    public void receive(String msg) {
        System.out.println("TopicTest receive: " + msg + ", receiveTime= " + System.currentTimeMillis());
    }
}
server.port=8091
spring.cloud.stream.rocketmq.binder.name-server=192.168.0.118:9876
spring.cloud.stream.bindings.input.destination=TopicTest
spring.cloud.stream.bindings.input.group=test-group1

消费事务消息与消费普通消息的代码是一样的,无需做任何修改。

事务消息的技术原理

RocketMQ采用了2PC的方案来提交事务消息。第一阶段Producer向Broker发送预处理消息,此时消息还未被投递出去,Consumer还不能消费;第二阶段Producer向Broker发送提交或者回滚消息。具体流程如下:

  • 发送预处理消息成功后,开始执行本地事务。
  • 如果本地事务执行成功,发送提交请求提交事务消息,消息会投递给Consumer
    在这里插入图片描述
  • 如果本地事务执行失败,发送回滚请求回滚事务消息,消息不会投递给Consumer
    在这里插入图片描述
  • 如果本地事务状态未知,网络故障或Producer宕机,Broker未收到二次确认的消息。由Broker端发送请求给Producer进行消息回查,确认提交或回滚。如果消息状态一致未被确认,需要人工介入处理。
RocketMQ事务消息的最佳实践 在分布式的场景下,我们经常能遇到事务一致性问题,如何去保证事务的一致性,是分布式场景下不可避免的一个重要话题。 我们很难去做到事务的强一致性(有方案),因此会退一步去保证事务的最终一致性。 如何去保证事务的最终一致性呢?我们可以利用RocketMQ的事务消息来保证事务的最终一致性。 RocketMQ如何保证事务的一致性呢?原来,RocketMQ通过将应用本地事务和发送消息操作定义到全局事务中,要么同时成功,要么同时失败。这样就保证了本地事务和消息发送的一致性: 事务消息的原理可以参考事务消息以及收发事. 阅读详情

相关推荐

《使用RocketMQ 做Spring Cloud异步场景分布式事务》

作者:陶陶技术笔记 链接:https://www.cnblogs.com/zlt2000/p/11570917.html?utm_source=tuicool&utm_medium=referral 一、背景 在微服务架构中,我们常常使用异步化的手段来提升系统的吞吐量和解耦上下游,而构建异步架构最常用的手段就是使用 消息队列(MQ) ,那异步架构怎样才能实现数据...

公众号【Java大蜗牛】 550

RocketMQ事务消息机制

RocketMQ提供了事务消息,通过事务消息就能达到分布式事务的最终一致,从而实现了可靠消息服务。 一、事务消息的实现步骤 事务消息发送步骤: 1. 发送方将半事务消息发送至RocketMQ服务端。 2. RocketMQ服务端将消息持久化之后,向发送方返回Ack确认消息已经发送成功。由于消息为半事务消息,在未收到生产者对该消息的二次确认前,此消息被标记成“暂不能投递”状态。 3. 发送方开始执行本地事务逻辑。 4. 发送方根据本地事务执行结果向服务端提交二次确认(Commit 或是 Rollbac

zsh2050的专栏 5342

RocketMQ的事务消息是如何实现的

高频面试题:RocketMQ的事务消息是如何实现的?

qq_30939943的博客 1067

消息队列重难点问题

消息队列 RabbitMQ Kafka RocketMQ 解耦 异步 削峰 如何保证消息不被重复消费 如何保证消息传输的可靠性 如何保证消息的顺序性 如何解决消息积压 如果要自己实现一个消息队列,架构设计应该是怎样的 kafka为什么能实现高吞吐量

weixin_43111776的博客 1738

RocketMQ的事务消息是如何实现的?

那如果用事务消息,先提交一个半消息,然后执行本地事务,在发送一个commit的半消息。4.回滚事务消息:如果本地事务执行失败,应用程序通知RocketMQ Broker 回滚该事务,RocketMQ将该消息的状态从‘prepared’改为‘rollback’,并将该消息从事务消息日志中删除,从而保证该消息不会被消费者消费。在发送事务消息时,首先向RocketMQ Broker 发送一条‘half消息’(半消息),半消息将被存储在broker端的事务消息日志中,但是这个消息还不能被消费者消费。

zhangjiaming_zjm的博客 893

【JAVA面试】RocketMQ实现事务消息

提示:文章先作为初版,等后续时间充足后,补充更深的内容。

Gangangan_的博客 1637

SpringCloud集成RocketMQ实现事务消息方案

前边的话 当前SpringCloud作为微服务开发的首选开源方案提供了完善的微服务开发技术套件,不过针对分布式领域的难题–分布式事务控制并没有成熟的方案,本篇将介绍作为柔性事务控制的优秀方案RocketMQ的使用原理和方法。 通过本案例的学习,掌握SpringCloud集成RocketMQ事务分布式事务控制的方法。 分布式事务控制系列文章 分布式事务视频教程下载 RocketMQ事务消息方案 RocketMQ 是一个来自阿里巴巴的分布式消息中间件,于 2012 年开源,并在 2017 年正式成为 Apach

3万+

RocketMQ事务消息实现原理

文章目录概述RocketMQ事务消息实现原理RocketMQ事务消息流程概要RocketMQ事务消息设计事务消息优缺点优势缺陷注意 概述 在之前文章seata(一) 分布式事务解决方案汇总中介绍了十来种分布式事务的解决方案或理论,其中有一个是事务消息。rocketmq是支持事务消息的,本文将介绍rocketmq事务消息的实现原理,以及具体实例。 RocketMQ事务消息实现原理 RocketMQ是基于2PC协议基础之上演变而来的,同时增加一个补偿(回查)逻辑来处理二阶段超时或者失败的消息。2PC协议可以参

刘本龙的专栏 2174

RocketMQ中事务消息的实现机制

理解RocketMQ事务消息的实现机制,可以帮助开发者更好地设计分布式系统中的事务处理逻辑,确保数据的一致性和可靠性。

2201_75353178的博客 1576

汇川AM系列PLC玩转CNC:手把手教你用File模式读取G代码文件(附避坑指南)

本文详细介绍了如何使用汇川AM系列PLC的File模式读取G代码文件,涵盖从CAD设计到PLC配置的全流程。特别针对路径格式、文件类型等常见问题提供避坑指南,帮助工程师快速实现CNC加工的自动化控制。

weixin_33582311的博客 398

EPICS pythonSoftIOC教程

EPICS pythonSoftIOC教程

yuyuyuliang00的博客 1516

RocketMQ第8讲——事务消息实现原理

在发送事务消息时,首先会向Broker发送一条“half消息”(即半消息),此时的半消息还不能被消费者消费到,接下来,在半消息发送成功后,应用程序通过本地事务的执行情况来确定是否要提交该事务消息,如果本地事务执行成功,那么就会通知Broker提交,这时消费者就能消费到这条消息了;回滚事务消息:如果本地事务执行失败,程序会通知Broker回滚该事务消息,状态由“prepared”改为“rollback”,并将该消息删除,从而保证不被消费者消费到。如果执行成功,则通知Broker提交该事务消息。

让~学习~成为一种习惯(橡 皮 人の技术博客) 2141

DDoS攻击--Syn_Ack/Ack_Flood等攻击防护详解(TCP)

前言 Syn_Ack/Ack_Flood攻击属于TCP攻击,在了解Syn_Ack/Ack_Flood攻击之前,可以先看看TCP攻击详解。 Syn_Ack Flood 攻击: syn_ack报文出现在连接建立的第2个报文,用来确认第一次握手的syn包。 当服务器收到syn_ack报文后会在系统里查询是否属于3次握手的范畴。如果属于则回复ack,并将连接设为连接状态。若没有查到相关信息,则回复...

一只IT小小鸟 1万+

RocketMQ事务消息是如何实现的?

首先,事务消息的大致流程应该是这样的:生产者发送一个半消息(Half Message)到Broker,Broker会将这个消息标记为“暂时不可见”,也就是对消费者不可见。之前写过相关的RocketMQ文章,其中涉及的到Rocket如何解决消息丢失问题,而文章中给出的是,在生产者进行优化是:同步发送+重试+事务消息。另外,事务消息的实现可能涉及两阶段提交(2PC)的思想,但RocketMQ并没有完全实现标准的2PC,而是通过异步检查和重试机制来简化流程,提高性能。确保消息发送与本地事务的最终一致性。

qq_39126115的博客 1366

ICC II 时钟树综合(CTS)前奏:从约束定义到NDR规则的全方位设置指南

本文详细介绍了ICC II中时钟树综合(CTS)的前期准备工作,包括约束定义、NDR规则设置和时钟平衡点控制等关键步骤。通过实际案例和代码示例,指导工程师如何优化时钟偏斜、插入延迟和信号质量,确保芯片设计的时序收敛和性能稳定。特别强调了非默认布线规则(NDR)在时钟网络设计中的重要性。

weixin_42530458的博客 210

机器学习预测股票收益(一)之随机森林模型

机器学习预测股票收益(一)前言一、导入库和数据二、处理数据以及计算特征变量三、使用随机森林回归预测股票收益1.构建训练集和测试集2.查看预测结果四、根据预测结果构建long-short投资组合1.定义投资组合函数2.定义绩效分析函数五、引入Fama-French Factor六、投资组合表现1.超额收益表现2.多因子回归总结 前言 本文将使用Python整理1927-2020年所有美国上市公司股票数据。根据历史收益以及交易量,使用随机森林,支持向量机以及神经网络等机器学习方法预测股票收益。最优结果构建的资产

weixin_47174968的博客 1万+

RocketMQ事务消息是如何实现的?

RocketMQ事务消息是如何实现的?

java1234的博客 1097

Linux之SUSE系统SAP-HANA经常系统内存不足使得SAP应用不能使用解决方案

问题描述 Linux内存使用量超过阈值,使得sap应用程序无可用内存,最终导致程序崩溃。 问题原因 自己查阅了一些资料,也基于zabbix的可用内存和实际不太一样入手去找原因发现问题出现于Cached的值过大,导致系统没有可以再分配的内存空间。Cached只要用来缓存文件的,经常读写的文件会被缓存到Cached中,可以增加读写效率,该功能是Linux系统内核提供的,而SAP-HANA的日志文件很大...

liuxiangyang_的博客 6699

RocketMQ事务消息实现分布式事务

RocketMQ事务消息RocketMQ在4.3.0版中支持分布式事务消息,这里RocketMQ的事务消息是采用2PC(两段式协议) +补偿机制(消息回查)的分布式事务功能。提供消息发送与业务落库的一致性。RocketMQ事务消息(Transactional Message)是指应用本地事务和发送消息操作可以被定义到全局事务中,要么同时成功,要么同时失败。RocketMQ的事务消息提供类似 X/Open XA 的分布式事务功能,通过事务消息能达到分布式事务的最终一致。

刘皇叔说Java的博客 1693

如何使用Python爬取并保存网页上的所有附件

爬虫(Crawler)是一种自动化程序,它通过模拟人工访问网页并下载网页上的数据或文件,常用于数据采集和分析。爬虫通常以“爬取”的形式自动浏览和提取网页中的各种信息。本文详细介绍了如何使用Python爬取并保存网页中的附件文件,涵盖了网页解析、文件下载、多线程与异步优化等内容。希望通过本文的讲解,能够帮助你理解并掌握附件爬取的技巧。在实际应用中,爬虫开发不仅需要解决技术问题,还要遵守网络道德和法律法规,避免不当使用爬虫造成负面影响。

2201_76125261的博客 957

华为OD机考双机位C卷 - 池化资源共享 (Java & Python& JS & C/C++ & GO )

华为OD机考双机位C卷 - 池化资源共享 (OD上机考试双机位C卷)。提供Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。

算法大师! 1064

图解RocketMQ之如何实现事务消息

我们先想象一个场景:从用户 A 的账户中扣减 100 元。向用户 B 的账户中增加 100 元。这两个步骤要么都成功,要么都失败。如果在步骤 1 扣减了100元,但步骤 2 增加时发生了错误,我们希望,用户A的账户金额恢复到原来的状态。上面是一个典型的事务场景,什么是事务?,简而言之,事务是逻辑上的一组操作,要么都执行,要么都不执行。下面有一道经典的八股,衡量事务的四大特性的了解程度,理解的背一下就好了。

一个成长中的程序员,期待用技术的眼光生活 1722

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

RocketMq之事务消息实现原理

RocketMQ提供了事务消息的功能,采用(两阶段协议)+补偿机制(事务回查)的分布式事务功能,通过这种方式能达到分布式事务的最终一致。

xl2790631的博客 919

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

RocketMQ事务消息实现原理分析

1. 前言 RocketMQ采用2PC的思想,实现了Producer发送「事务消息」。事务消息的提交分为两个阶段,阶段一,Producer发送半事务(Half)消息到Broker,Broker存储消息,然后响应消息写入结果,此时消息对Consumer是不可见的。阶段二,Producer根据消息发送结果做对应的处理,如果消息发送成功,则开始执行本地事务,并提交事务状态给Broker,事务状态有三种,对应的Broker动作为: COMMIT_MESSAGE:事务提交,消息对Consumer可见。 ROLLBA

程序员小潘 2701

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

上一篇: itextpdf在PDF指定位置添加文本
下一篇: RocketMQ - 高可用设计
无法无天过路客
博客等级 码龄11年 1191粉丝 240原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无法无天过路客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值