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. SPI、IIC、IIS、UART、JTAG的应用场合级区别

    SPI  SPI接口的全称是"Serial Peripheral Interface",意为串行外围接口,是Motorola首先在其MC68HCXX系列处理器上定义的. SPI接口 ...

  2. Java开发中的23种设计模式详解(1)创建型

    设计模式(Design Patterns) --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...

  3. 利用Swiperefreshlayout实现下拉刷新功能的技术探讨

    在常见的APP中通常有着下拉页面从而达到刷新页面的功能,这种看似简单的功能有着花样繁多的实现方式.而利用Swiperefreshlayout实现下拉刷新功能则是其中比较简明扼要的一种. 一般来说,在竖 ...

  4. Redis主从配置,哨兵,集群的设计原理

    一 前言 谈到Redis服务器的高可用,如何保证备份的机器是原始服务器的完整备份呢?这时候就需要哨兵和复制. 哨兵(Sentinel):可以管理多个Redis服务器,它提供了监控,提醒以及自动的故障转 ...

  5. for循环(C语言型)举例

  6. Qt 【widget如何铺满窗口】

    刚接触qt不是很长时间,都是使用ui拖拽控件实现界面,然后发现有些问题就是控件一旦多了起来,拖拽就不好控制了,然后就转而使用纯代码开发. 一下是碰到第一个问题: 创建一个MainWidget; Mai ...

  7. 【JavaWeb项目】一个众筹网站的开发(二)架构搭建之架构测试

    1.dao层和pojo都是使用mbg生成,基本的CRUD以及JavaBean 2.将mbg放在dao层,一旦dao层打包以后mbg就删除掉 一.创建数据库用于测试 数据库名称:scw_0325 SQL ...

  8. Halo(五)

    ApplicationPreparedEvent 监听事件 Event published once the application context has been refreshed but be ...

  9. MariaDB 选择查询

    在本章中,我们将学习如何从表中选择数据. SELECT语句检索所选行. 它们可以包括UNION语句,排序子句,LIMIT子句,WHERE子句,GROUP BY ... HAVING子句和子查询. 查看 ...

  10. boost scope exit

    Boost.ScopeExit provides the macro BOOST_SCOPE_EXIT, which can be used to define something that look ...