如何用RocketMQTemplate发送事务消息

Transactional Message:通过两阶段提交保证本地事务与消息发送的一致性(如订单支付成功后发送物流消息)

在SpringBoot中通过RocketMQTemplate发送事务消息,需结合事务监听器实现本地事务与消息的一致性,通常是sendMessageInTransaction。使用这个方法需要以下几个步骤:

创建事务监听器:实现RocketMQLocalTransactionListener接口,重写executeLocalTransaction和checkLocalTransaction方法。executeLocalTransaction用于执行本地事务,checkLocalTransaction用于事务回查。

注入事务监听器:通过@RocketMQTransactionListener注解将监听器注入Spring容器,并指定对应的RocketMQTemplate实例(如果有多个的话)。

使用RocketMQTemplate发送事务消息:调用sendMessageInTransaction方法,传入topic、消息内容、以及本地事务的参数。

需要注意的是,事务消息的发送需要确保本地事务的执行结果能够正确反馈给RocketMQ,以便Broker决定提交还是回滚半事务消息。此外,事务监听器的实现需要处理本地事务的执行和回查逻辑。

  1. 定义事务监听器(核心)

实现RocketMQLocalTransactionListener接口,重写本地事务执行和回查方法,通过@RocketMQTransactionListener注解注入Spring容器。

java 复制代码
import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;  
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;  
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;  
import org.springframework.messaging.Message;  

@RocketMQTransactionListener(  
    rocketMQTemplateBeanName = "rocketMQTemplate" // 关联指定的RocketMQTemplate实例(默认可不填)  
)  

public class TransactionListenerImpl implements RocketMQLocalTransactionListener {  

    /**  
     * 执行本地事务  
     * @param msg 半事务消息  
     * @param arg 发送消息时传入的参数(可用于传递业务数据)  
     * @return 事务状态:COMMIT(提交)、ROLLBACK(回滚)、UNKNOWN(需要回查)  
     */  
    @Override  
    public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) {  
        try {  
            // 1. 执行业务逻辑(如数据库操作、订单创建等)  
            String orderId = (String) arg; // 从arg中获取业务参数  
            System.out.println("执行本地事务,订单ID:" + orderId);  
            // 2. 业务成功,返回COMMIT  
            return RocketMQLocalTransactionState.COMMIT;  
        } catch (Exception e) {  
            // 3. 业务失败,返回ROLLBACK  
            return RocketMQLocalTransactionState.ROLLBACK;  
        }  
    }

    /**  
     * 事务回查(当Broker未收到本地事务结果时触发)  
     * @param msg 半事务消息  
     * @return 事务状态:COMMIT(提交)、ROLLBACK(回滚)、UNKNOWN(继续回查)  
     */  
    @Override 
    public RocketMQLocalTransactionState checkLocalTransaction(Message msg) {  
        // 1. 检查本地事务执行结果(如查询数据库中订单状态)  
        String orderId = msg.getHeaders().get("ORDER_ID", String.class);  
        System.out.println("回查本地事务,订单ID:" + orderId);  
        // 2. 根据实际状态返回结果(示例:假设查询到订单已成功,返回COMMIT)  
        return RocketMQLocalTransactionState.COMMIT;  
    }  
}
  1. 使用RocketMQTemplate发送事务消息

调用rocketMQTemplate.sendMessageInTransaction方法,传入事务消息参数(Topic、消息体、本地事务参数)。

java 复制代码
import org.apache.rocketmq.spring.core.RocketMQTemplate;  
import org.springframework.messaging.support.MessageBuilder;  
import org.springframework.stereotype.Component;  
import javax.annotation.Resource;  

@Component  
public class TransactionProducer {  
    @Resource  
    private RocketMQTemplate rocketMQTemplate;  

    /**  
     * 发送事务消息  
     * @param topic 消息主题(格式:"topic:tag",如"OrderTopic:create")  
     * @param orderId 业务参数(如订单ID,将传递给事务监听器)  
     */  
    public void sendTransactionMessage(String topic, String orderId) {  
        // 1. 构建消息(可添加自定义头信息,用于回查)  
        org.springframework.messaging.Message<String> message = MessageBuilder  
            .withPayload("订单创建消息:" + orderId) // 消息体  
            .setHeader("ORDER_ID", orderId) // 自定义头信息(回查时使用)  
            .build();  

        // 2. 发送事务消息  
        // 参数:topic、消息对象、本地事务参数(会传递给executeLocalTransaction的arg)  
        rocketMQTemplate.sendMessageInTransaction(topic, message, orderId);  
    }  
}
  1. 关键配置与注意事项

依赖与版本

确保rocketmq-spring-boot-starter和rocketmq-client版本匹配(推荐的2.3.1+5.3.0),避免版本冲突。

事务监听器与RocketMQTemplate绑定

若项目中有多个RocketMQTemplate实例(通过@ExtRocketMQTemplateConfiguration创建),需在@RocketMQTransactionListener中通过rocketMQTemplateBeanName指定对应的模板名称,确保监听器与生产者关联。

本地事务幂等性

由于事务回查可能多次触发,executeLocalTransaction和checkLocalTransaction方法需保证幂等性(如通过订单ID判断是否已处理)。

事务状态返回

executeLocalTransaction返回UNKNOWN时,Broker会在间隔时间后触发回查(默认60秒,可通过transactionCheckInterval配置),最多回查15次(默认,可通过transactionCheckMax配置)。

  1. 测试流程

调用TransactionProducer.sendTransactionMessage("OrderTopic", "123456")发送事务消息。

RocketMQ会先发送半事务消息(消费者不可见),然后执行executeLocalTransaction。

若返回COMMIT,半事务消息转为可见,消费者可消费;若返回ROLLBACK,消息被丢弃;若返回UNKNOWN,触发checkLocalTransaction回查。

通过以上步骤,即可基于RocketMQTemplate实现事务消息的发送,确保本地业务与消息传递的一致性。

相关推荐
SimonKing9 分钟前
SpringBoot 集成 SSE 实现服务端推送或可代替Websocket
java·后端·程序员
不正经的码狗12 分钟前
JAVA 、Eclipse 安装及配置 JAVA 项目(无需配置环境)
java·eclipse
xiaoqiMikko20 分钟前
你升的是 jackson-databind,中招的是 jackson-core:一个超长 JSON key 就能吃掉 200MB 堆
java·安全
不正经的码狗24 分钟前
Eclipse汉化(快速,推荐)
java·eclipse
极客互动API26 分钟前
极客互动-企业微信基于外部API接口实现AI客服自动接管外部联系人消息收发
java·微信·企业微信·ai编程·rpa
Sam_Deep_Thinking28 分钟前
关于java final关键字的可见性
java·后端·面试·程序员
tryxr30 分钟前
矩阵的几种基础变换
java·数据结构·算法·矩阵
写后端的胖头鱼31 分钟前
如何区分IO/CPU 密集型,线程池核心参数怎么设置
java·线程池·多线程·io密集·cpu密集
JAVA面经实录9171 小时前
IDEA 开发知识
java·intellij-idea·idea
于樱花森上飞舞1 小时前
【Redis】哨兵详解
java·开发语言·数据库·redis