mq事务介绍

mq事务消息流程

  1. 生产者发送消息到mq,消息状态为:SEND_OK。此消息是消费者不可见(消费者无法消费此条消息)
  2. 执行本地任务:成功则返回COMMIT_MESSAGE,此时消费者可消费此条消息。失败则返回ROLLBACK_MESSAGE,此时删除mq的此条消息
  3. 如果消息一定时间后没有被确认(COMMIT_MESSAGE)也没有被删除(ROLLBACK_MESSAGE),则mq回调一个方法,主动确认本地事务是否成功,主动要求确认消息状态。

1、配置文件

详情见:https://www.cnblogs.com/happydreamzjl/p/12022412.html

2、生产者

1、生产者配置

package com.gofun.customer.mqTrans;

import com.gofun.customer.mq.RocketMqProducerProperties;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.TransactionMQProducer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import java.util.concurrent.*; @Configuration
@EnableConfigurationProperties(RocketMqProducerProperties.class)
@ConditionalOnProperty(prefix = "rocketmq.producer", name = "iseffect", havingValue = "true")
public class RocketMqTransConfig {
@Autowired
private RocketMqProducerProperties rocketMqProperties; private final int corePoolSize = 2;//消费最小线程数
private final int maximumPoolSize = 5;//消费最大线程数
private final long keepAliveTime = 100;//线程活跃时间
private final TimeUnit timeUnit = TimeUnit.SECONDS;//keepAliveTime时间单位
private final int capacity = 2000;//保存任务的队列容量 @Bean
@ConditionalOnProperty(prefix = "rocketmq.producer", name = "type", havingValue = "transaction")
public TransactionMQProducer transactionMQProducer() throws MQClientException {
TransactionMQProducer transactionMQProducer = new TransactionMQProducer(rocketMqProperties.getGroupName()); ExecutorService executorService = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, timeUnit,
new ArrayBlockingQueue<Runnable>(capacity), new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setName("client-transaction-msg-check-thread");
return thread;
}
});
transactionMQProducer.setNamesrvAddr(rocketMqProperties.getNamesrvAddr());
transactionMQProducer.setExecutorService(executorService);
transactionMQProducer.start();
return transactionMQProducer;
} }

生产者发送工具类

package com.gofun.customer.mqTrans;

import com.alibaba.fastjson.JSON;
import com.gofun.customer.mq.RocketMqProducerProperties;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.TransactionListener;
import org.apache.rocketmq.client.producer.TransactionMQProducer;
import org.apache.rocketmq.common.message.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; @Component
public class RocketMqTransProducer {
@Autowired
private TransactionMQProducer transactionMQProducer;
@Autowired
private RocketMqProducerProperties rocketMqProperties; public void setListener(TransactionListener listener) {
transactionMQProducer.setTransactionListener(listener);
transactionMQProducer.setSendMsgTimeout(10000);
} public SendResult send(String topic, String tag, Object obj) {
Message msg = new Message(topic, tag, getBody(obj));
SendResult sendResult = null;
try {
sendResult = transactionMQProducer.sendMessageInTransaction(msg, null);
} catch (Exception e) {
}
return sendResult;
} public SendResult send(String tag, Object obj) {
Message msg = new Message(rocketMqProperties.getTopicName(), tag, getBody(obj));
SendResult sendResult = null;
try {
sendResult = transactionMQProducer.sendMessageInTransaction(msg, null);
} catch (Exception e) {
}
return sendResult;
} private byte[] getBody(Object obj) {
String body = null;
if(obj == null){
return null;
}
if(obj instanceof String){
body = (String) obj;
}else{
body = JSON.toJSONString(obj);
}
return body.getBytes();
} }

2、本地事务和超时mq回调方法

package com.gofun.customer.controller.test;

import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.client.producer.TransactionListener;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageExt;
import org.springframework.stereotype.Component; import java.util.Random; @Component
public class TestTransactionListener implements TransactionListener {
private static boolean transStatus = true; /**
* 执行本地事务
*
* @param message
* @param o
* @return
*/
@Override
public LocalTransactionState executeLocalTransaction(Message message, Object o) {
System.out.println("用一个随机数模拟本地任务执行成功或失败");
Random random = new Random();
transStatus = random.nextBoolean();
if (transStatus) {
System.out.println("执行本地任务成功。。。。。。");
return LocalTransactionState.COMMIT_MESSAGE;
}
System.out.println("执行本地任务失败。。。。。");
return LocalTransactionState.ROLLBACK_MESSAGE;
} /**
* mq长时间收不到提交消息,会执行此方法,检查本地事务是否成功
* @param messageExt
* @return
*/
@Override
public LocalTransactionState checkLocalTransaction(MessageExt messageExt) {
System.out.println("获取本地任务执行成功或失败");
if (transStatus) {
System.out.println("判断本地任务成功。。。。");
return LocalTransactionState.COMMIT_MESSAGE;
}
System.out.println("判断本地任务失败。。。。");
return LocalTransactionState.ROLLBACK_MESSAGE;
}
}
  1. 实现接口TransactionListener
  2. executeLocalTransaction 方法内执行本地事务,并且判断事务是否成功,成功返回LocalTransactionState.COMMIT_MESSAGE,失败返回:LocalTransactionState.ROLLBACK_MESSAGE;
  3. LocalTransactionState.ROLLBACK_UNKNOW 是中间状态,该消息正在检查中,等待检查结果后执行上述两个状态
  4. checkLocalTransaction 方法是mq 长时间处于UNKNOW 状态时会调用此方法,主动请求确认消息状态。

3、发送事务消息

1、引入发送事务消息的工具类

@Autowired
private RocketMqTransProducer rocketMqProducer;
@Autowired
private TestTransactionListener testTransactionListener;

2、发送消息

rocketMqProducer.setListener(testTransactionListener);
SendResult sendResult = rocketMqProducer.send("testTag", "测试mq发送消息。。。。");
if (sendResult != null) {
SendStatus sendStatus = sendResult.getSendStatus();
System.out.println("发送消息返回:" + sendStatus.toString());
} else {
System.out.println("发送消息失败");
}

3、消费者

消费者与非事务性消费者相同见:https://www.cnblogs.com/happydreamzjl/p/12022412.html

4、消费者消费情况

  1. 可看到本地任务成功时消费者消费了消息,本地任务失败时没有消费消息(消息没有发送成功)

转自:https://blog.csdn.net/Cy_LightBule/article/details/88891844

https://www.jianshu.com/p/5260a2739d80

RocketMQ事务性消息的更多相关文章

  1. RocketMQ事务性消息及持久化

    TransactionProducer(事务消息): 在分布式系统中,我们时常会遇到分布式事务的问题,除了常规的解决方案之外,我们还可以利用RocketMQ的事务性消息来解决分布式事务的问题.Rock ...

  2. rocketmq总结(消息的高可用、中间件选型)

    rocketmq总结(消息的高可用.中间件选型) 参考: https://blog.csdn.net/meilong_whpu/article/details/76922456 http://blog ...

  3. JMS - 事务性消息

    JMS 事务遵从发送操作与接收操作相互分离的约定.下图显示的是一个事务性发送,其中一组消息要么能够保证全部到达消息服务器,要么连一条消息也不能保证到达消息服务器.从发送者的角度来看,JMS 提供者为这 ...

  4. RocketMQ源码 — 九、 RocketMQ延时消息

    上一节消息重试里面提到了重试的消息可以被延时消费,其实除此之外,用户发送的消息也可以指定延时时间(更准确的说是延时等级),然后在指定延时时间之后投递消息,然后被consumer消费.阿里云的ons还支 ...

  5. 聊一聊顺序消息(RocketMQ顺序消息的实现机制)

    当我们说顺序时,我们在说什么? 日常思维中,顺序大部分情况会和时间关联起来,即时间的先后表示事件的顺序关系. 比如事件A发生在下午3点一刻,而事件B发生在下午4点,那么我们认为事件A发生在事件B之前, ...

  6. RocketMQ源码分析之RocketMQ事务消息实现原理上篇(二阶段提交)

    在阅读本文前,若您对RocketMQ技术感兴趣,请加入 RocketMQ技术交流群 根据上文的描述,发送事务消息的入口为: TransactionMQProducer#sendMessageInTra ...

  7. RocketMQ事务消息实现分析

    这周RocketMQ发布了4.3.0版本,New Feature中最受关注的一点就是支持了事务消息: 今天花了点时间看了下具体的实现内容,下面是简单的总结. RocketMQ事务消息概要 通过冯嘉发布 ...

  8. RocketMQ之消息幂等

    幂等(idempotent.idempotence)是一个数学与计算机学概念,常见于抽象代数中. 在编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同. 首先我们了解一下什么是 ...

  9. rocketmq总结(消息的顺序、重复、事务、消费模式)

    rocketmq总结(消息的顺序.重复.事务.消费模式) 参考: http://www.cnblogs.com/wxd0108/p/6038543.html https://www.cnblogs.c ...

随机推荐

  1. html中a标签伪类的优先级与顺序

    /** 这四个伪类的优先级相同,前一个会覆盖后一个 建议书写顺序: lvha => love hate(好记) */ a:link { color: red; } a:visited { col ...

  2. CSS实现不换行/自动换行/文本超出隐藏显示省略号

    在写页面的时候,我们经常会需要用到关于文本的换行,强制换行以及显示几行超过显示省略号等,今天我们就对这些问题来做个汇总吧! 1.自动换行 div{ word-wrap:break-word; word ...

  3. MAC如何与linux服务器传递文件

    scp命令可以从本地拷贝文件到Linux服务器,也可以将Linux服务器文件下载到本地 将远程/root/articaleFetch/dist目录下文件和文件夹拷贝到dist文件夹 scp root@ ...

  4. noip2010机器翻译

    以下题面摘自洛谷1540 题目背景 小晨的电脑上安装了一个机器翻译软件,他经常用这个软件来翻译英语文章. 题目描述 这个翻译软件的原理很简单,它只是从头到尾,依次将每个英文单词用对应的中文含义来替换. ...

  5. 转 Tomcat访问日志详细配置

    配置http访问日志.Tomcat自带的能够记录的http访问日志已经很详细了取消下面这段的注释: <Valve className="org.apache.catalina.valv ...

  6. SQL的子查询与JOIN的小试牛刀

    //学生表CREATE TABLE student( ID INT PRIMARY KEY, s_name ) NOT NULL, class_id INT NOT NULL); , "qf ...

  7. windows10 配置SSH连接Github、配置SSH Key

    由于你的本地Git仓库和GitHub仓库之间的传输是通过SSH加密的,所以,需要设置SSH key. 第1步:创建SSH Key.在用户主目录下[我的电脑是C:\Users\ad],看看有没有.ssh ...

  8. nodejs npm 常用配置

    npm install moduleNames : 安装 Node 模块.node安装分为全局模式和本地模式. npm install -g moduleName.npm install expres ...

  9. PostgreSQL按年月日分组(关键词:extract time as Year/Month/Day)

    Select EXTRACT(year from cast(joindate as timestamp)) as Year, EXTRACT(month from cast(joindate as t ...

  10. Jetson Nano系列教程3:GPIO

    摘要: JetsonTX1,TX2,AGXXavier和Nano开发板包含一个40引脚的GPIO头,类似于Raspberry PI中的40引脚头.这些GPO可以通过JetsonGPIOLibrary包 ...