如何用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实现事务消息的发送,确保本地业务与消息传递的一致性。

相关推荐
人道领域6 小时前
Java基础热门八股总结:八种基本数据类型 + 装箱拆箱 + 缓存机制,(90%的Java新手都搞不清的装箱拆箱问题)
java·开发语言·python
菜鸟小九6 小时前
JUC补充(ThreadLocal、completableFuture)
java·开发语言
Seven976 小时前
两小时入门Sentinel
java
tongluowan0077 小时前
Java中atomic底层原理 - ABA 问题与解决方案
java·juc·atomic
无关86887 小时前
Spring Boot 项目标准化部署打包实战
java·spring boot·后端
jay神7 小时前
基于微信小程序课外创新实践学分认定系统
java·spring boot·小程序·vue·毕业设计
Gauss松鼠会7 小时前
GaussDB(DWS) GUC参数修改、查看
java·数据库·sql·数据库开发·gaussdb
AIFQuant7 小时前
Java 对接全球股票实时报价:高可用架构与异常处理
java·开发语言·websocket·金融·架构·股票api
未若君雅裁7 小时前
Spring Bean 作用域、线程安全与生命周期
java·安全·spring