Spring Cloud Alibaba学习笔记(11) - RocketMQ事务消息
在Spring中,我们要实现事务,一般通过@Transactional注解实现。这在引入RocketMQ之前没有问题,但是在引入了RocketMQ之后,如果消息发送之后的业务逻辑处理发生了异常的话,这时候消息已经发送出去了,就会导致业务的问题。
为了解决这一问题,RocketMQ引入了Transactional Message【事务消息】。

- 生产者向MQServer发送半消息【半消息:会存储进MQ Server,但是被标记为不能投递状态】
- 发送半消息成功,生产者实行本地事务
- 根据本地事务结果向MQ Server发送二次确认请求
- MQ Server根据接受到的消息投递或者丢弃消息
- 若在本地事务执行过程中缺少二次确认消息或生产者处于等待状态,MQ服务器将向同一组中的每个生产者发送检查消息,然后继续3,4的操作
PS:消息三态
- Commit:提交事务信息,消费者可以消费此消息
- Rollback:回滚事务消息,broker会删除这条消息,消费者不能消费
- UNKNOWN:broker需要回查确认消息状态
代码实现
发送半消息
利用rocketMQTemplate类的sendMessageInTransaction实现半消息发送
第一个参数为txProducerGroup:就是group名称,根据业务自定义
第二次信息为destination:topic名称
第三个信息为message:消息体,利用MessageBuilder.withPayload构建
第四个信息为arg:业务对象,用于处理本地业务
代码如下:
// 发送半消息
rocketMQTemplate.sendMessageInTransaction(
"test-transactional",
"test-topic",
MessageBuilder.withPayload(
Demo.builder().demoId(1).remark("哈哈哈").build()
).setHeader(RocketMQHeaders.TRANSACTION_ID, UUID.randomUUID().toString()).build(),
forObject
);
实现RocketMQLocalTransactionListener接口
新建demoTransactionalListener类,继承RocketMQLocalTransactionListener接口,实现了两个方法
executeLocalTransaction:处理本地业务
checkLocalTransaction:MQ Server发送检查信息相应
添加@RocketMQTransactionListener注解,txProducerGroup属性值与半消息的txProducerGroup参数值相同
代码如下:
import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
import org.apache.rocketmq.spring.support.RocketMQHeaders;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
@RocketMQTransactionListener(txProducerGroup = "test-transactional")
public class demoTransactionalListener implements RocketMQLocalTransactionListener {
/**
* 处理本地事务
*/
@Override
public RocketMQLocalTransactionState executeLocalTransaction(Message message, Object arg) {
// 消息头
MessageHeaders headers = message.getHeaders();
String transactionalId = (String) headers.get(RocketMQHeaders.TRANSACTION_ID);
// arg:sendMessageInTransaction方法的第四个参数,用于处于本地业务
try {
// 本地业务
return RocketMQLocalTransactionState.COMMIT;
} catch (Exception e) {
return RocketMQLocalTransactionState.ROLLBACK;
}
}
/**
* 若在本地事务执行过程中缺少二次确认消息或生产者处于等待状态
* MQ Server将向同一组中的每个生产者发送检查消息
*/
@Override
public RocketMQLocalTransactionState checkLocalTransaction(Message message) {
try {
// 检查
return RocketMQLocalTransactionState.COMMIT;
} catch (Exception e) {
return RocketMQLocalTransactionState.ROLLBACK;
}
}
}
PS:MQ Server发送检查:可以通过新建一个表,记录本地业务成功或者失败,然后检查相应只需要查一下数据就可以了
Spring Cloud Alibaba学习笔记(11) - RocketMQ事务消息的更多相关文章
- Spring Cloud Alibaba学习笔记(1) - 整合Spring Cloud Alibaba
Spring Cloud Alibaba从孵化器版本毕业:https://github.com/alibaba/spring-cloud-alibaba,记录一下自己学习Spring Cloud Al ...
- Spring Cloud Alibaba学习笔记(14) - Spring Cloud Stream + RocketMQ实现分布式事务
发送消息 在Spring消息编程模型下,使用RocketMQ收发消息 一文中,发送消息使用的是RocketMQTemplate类. 在集成了Spring Cloud Stream之后,我们可以使用So ...
- Spring Cloud Alibaba学习笔记
引自B站楠哥:https://space.bilibili.com/434617924 一.创建父工程 创建父工程hello-spring-cloud-alibaba Spring Cloud Ali ...
- Spring Cloud Alibaba学习笔记(15) - 整合Spring Cloud Gateway
Spring Cloud Gateway 概述 Spring Cloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于Netty.Reactor以及WEbFlux构建,它 ...
- Spring Cloud Alibaba学习笔记(3) - Ribbon
1.手写一个客户端负载均衡器 在了解什么是Ribbon之前,首先通过代码的方式手写一个负载均衡器 RestTemplate restTemplate = new RestTemplate(); // ...
- Spring Cloud Alibaba学习笔记(22) - Nacos配置管理
目前业界流行的统一配置管理中心组件有Spring Cloud Config.Spring Cloud Alibaba的Nacos及携程开源的Apollo,本文将介绍Nacos作为统一配置管理中心的使用 ...
- Spring Cloud Alibaba学习笔记(2) - Nacos服务发现
1.什么是Nacos Nacos的官网对这一问题进行了详细的介绍,通俗的来说: Nacos是一个服务发现组件,同时也是一个配置服务器,它解决了两个问题: 1.服务A如何发现服务B 2.管理微服务的配置 ...
- Spring Cloud Alibaba学习笔记(10) - Spring消息编程模型下,使用RocketMQ收发消息
编写生产者 集成 添加依赖 <dependency> <groupId>org.apache.rocketmq</groupId> <artifactId&g ...
- Spring Cloud Alibaba学习笔记(12) - 使用Spring Cloud Stream 构建消息驱动微服务
什么是Spring Cloud Stream 一个用于构建消息驱动的微服务的框架 应用程序通过 inputs 或者 outputs 来与 Spring Cloud Stream 中binder 交互, ...
随机推荐
- Linux内存中的Cache真的能被回收吗? 【转】
在Linux系统中,我们经常用free命令来查看系统内存的使用状态.在一个RHEL6的系统上,free命令的显示内容大概是这样一个状态: [root@tencent64 ~]# free ...
- Apollo的基本使用及常见问题
1. 创建项目 在创建项目页面中填写相关项目信息,最后点击提交即可创建项目. 注意:应用Id必须唯一并且与客户配置的app.id一致. 2. 发布 进入对应项目可通过文本(批量)或者表格模式添加配置, ...
- Django微信小程序后台开发教程
本文链接:https://blog.csdn.net/qq_43467898/article/details/83187698Django微信小程序后台开发教程1 申请小程序,创建hello worl ...
- [转]Git 代码撤销、回滚到任意版本(当误提代码到本地或master分支时)
两种情况(场景) 情况一 代码还只在本地,未push到运程仓库,想把代码还原到上一次commit的代码,此时操作为代码撤销 解决方案: 1 git reset [--hard|soft|mi ...
- vue报错:There are multiple modules with names that only differ in casing.
今天写项目时,遇到报错信息如下: 经过多次排除及参考网上文章,最后找到问题所在 排查原因:1 .在引用组件时,路径大小写不对也会造成此报错,看例子:错误写法: 正确写法: 2.在组件使用vuex时,引 ...
- 贪心:leetcode 870. Advantage Shuffle、134. Gas Station、452. Minimum Number of Arrows to Burst Balloons、316. Remove Duplicate Letters
870. Advantage Shuffle 思路:A数组的最大值大于B的最大值,就拿这个A跟B比较:如果不大于,就拿最小值跟B比较 A可以改变顺序,但B的顺序不能改变,只能通过容器来获得由大到小的顺 ...
- IDEA子项目的相互依赖
A项目依赖B项目 一.B项目打包,执行install 这一步其实就是把你的项目打包到本地仓库,你可以在本地仓库看到相应的jar包 二.在A项目的pom.xml引入依赖可以了 当B项目修改后,需要重新打 ...
- ES6深入浅出-13 Proxy 与 Reflect-2.Proxy 代理
阮一峰http://es6.ruanyifeng.com/#docs/proxy MDN https://developer.mozilla.org/zh-CN/docs/Web/JavaScript ...
- 让pc端代码适用移动端——<meta name="viewport"
写的代码,在pc端运行正常,在移动端就很小很小,需要放大.这时候可引入这个标签 @参考博客 用法,在<head></head>中添加<meta name="vi ...
- Delphi : TStringList的Find,IndexOf和Sort
关键:Find要事先Sort排序,Indexof不用排序. TStringList内部查找相关的数据.待调试代码时才知道痛苦,浪费无数时间后,只得一步步跟踪,才发 现Find方法返回的Index总是错 ...