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

为了解决这一问题,RocketMQ引入了Transactional Message【事务消息】。

  1. 生产者向MQServer发送半消息【半消息:会存储进MQ Server,但是被标记为不能投递状态】
  2. 发送半消息成功,生产者实行本地事务
  3. 根据本地事务结果向MQ Server发送二次确认请求
  4. MQ Server根据接受到的消息投递或者丢弃消息
  5. 若在本地事务执行过程中缺少二次确认消息或生产者处于等待状态,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事务消息的更多相关文章

  1. Spring Cloud Alibaba学习笔记(1) - 整合Spring Cloud Alibaba

    Spring Cloud Alibaba从孵化器版本毕业:https://github.com/alibaba/spring-cloud-alibaba,记录一下自己学习Spring Cloud Al ...

  2. Spring Cloud Alibaba学习笔记(14) - Spring Cloud Stream + RocketMQ实现分布式事务

    发送消息 在Spring消息编程模型下,使用RocketMQ收发消息 一文中,发送消息使用的是RocketMQTemplate类. 在集成了Spring Cloud Stream之后,我们可以使用So ...

  3. Spring Cloud Alibaba学习笔记

    引自B站楠哥:https://space.bilibili.com/434617924 一.创建父工程 创建父工程hello-spring-cloud-alibaba Spring Cloud Ali ...

  4. Spring Cloud Alibaba学习笔记(15) - 整合Spring Cloud Gateway

    Spring Cloud Gateway 概述 Spring Cloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于Netty.Reactor以及WEbFlux构建,它 ...

  5. Spring Cloud Alibaba学习笔记(3) - Ribbon

    1.手写一个客户端负载均衡器 在了解什么是Ribbon之前,首先通过代码的方式手写一个负载均衡器 RestTemplate restTemplate = new RestTemplate(); // ...

  6. Spring Cloud Alibaba学习笔记(22) - Nacos配置管理

    目前业界流行的统一配置管理中心组件有Spring Cloud Config.Spring Cloud Alibaba的Nacos及携程开源的Apollo,本文将介绍Nacos作为统一配置管理中心的使用 ...

  7. Spring Cloud Alibaba学习笔记(2) - Nacos服务发现

    1.什么是Nacos Nacos的官网对这一问题进行了详细的介绍,通俗的来说: Nacos是一个服务发现组件,同时也是一个配置服务器,它解决了两个问题: 1.服务A如何发现服务B 2.管理微服务的配置 ...

  8. Spring Cloud Alibaba学习笔记(10) - Spring消息编程模型下,使用RocketMQ收发消息

    编写生产者 集成 添加依赖 <dependency> <groupId>org.apache.rocketmq</groupId> <artifactId&g ...

  9. Spring Cloud Alibaba学习笔记(12) - 使用Spring Cloud Stream 构建消息驱动微服务

    什么是Spring Cloud Stream 一个用于构建消息驱动的微服务的框架 应用程序通过 inputs 或者 outputs 来与 Spring Cloud Stream 中binder 交互, ...

随机推荐

  1. 阿里云ECS服务器环境搭建(1) —— ubuntu 16.04 图形界面的安装

    阿里云ECS服务器环境搭建(1) —— ubuntu 16.04 图形界面的安装1. 背景在我们购买阿里云ECS服务器之后,默认的系统环境是很干净的,我购买的是ubuntu16.04,远程登录进入之后 ...

  2. spring-data-mongodb中的MongoTemplate与MongoRepository及推荐

    SpringData支持两种关系数据存储技术: JDBCJPA ● SpringData 方法定义JPA规范: 1. 不是随便声明的,而需要符合一定的规范2. 查询方法以find | read | g ...

  3. linux内核在挂载ramdisk的过程中报错"RAMDISK: incomplete write (10739 != 32768)"如何处理?

    1. 原因 ramdisk大小不够 2. 解决方法 在启动变量bootargs中添加参数"ramdisk_size=10000000"即可

  4. linux内核是在哪里创建1号进程的?

    1. 请看rest_init的完整代码(不看也没关系,内核版本为5.2, init/main.c) noinline void __ref rest_init(void) { struct task_ ...

  5. 将C++资源文件读取出来

    HRSRC   hResource   =   FindResource(GetModuleHandle(NULL),     MAKEINTRESOURCE(IDR_CALC),   TEXT(&q ...

  6. 报错 react-hot-loader

    ./node_modules/element-react/dist/npm/es5/libs/animate/index.js Module not found: Can't resolve 'rea ...

  7. snmp oid 和厂商对应关系

    <node oid="default" name="Unknown" type="workstation"/><node ...

  8. yii webservice 提示:Procedure 'getSent' not present 错误的解决方法(转)

    其实根据常用的webservice清除缓存方法,在client端加入这样一句话: ini_set("soap.wsdl_cache_enabled", "0") ...

  9. web端自动化——Selenium3+python自动化(3.7版本)-chrome67环境搭建

    前言 目前selenium版本已经升级到3.0了,网上的大部分教程是基于2.0写的,所以在学习前先要弄清楚版本号,这点非常重要.本系列依然以selenium3为基础. 一.selenium简介 Sel ...

  10. 【MPEG】DVB / ATSC / ISDB区别

    硬件的区别: 欧洲“DVB标准”和美国“ATSC数字电视标准”的主要区别如下: (1)方形像素:在ATSC标准中采纳了“方形像素”(Square Picture Eelements),因为它们更加适合 ...