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

相关推荐
Flittly1 天前
【AgentScope Java新手村系列】(16)从RAG到多路检索
java·spring boot·spring
小兔崽子去哪了1 天前
Java 生成二维码解决方案
java·后端
人活一口气1 天前
从JVM调优到MCP协议:Java全栈技术体系深度总结与企业级架构实践
java·spring boot
NE_STOP1 天前
Vibe Coding -- 完整项目案例实操
java
荣码1 天前
GraphRAG:普通RAG只能回答"点"的问题,我踩了4个坑才搞懂
java·python
SimonKing1 天前
Google第三方授权登录
java·后端·程序员
明月光8181 天前
从一行 @Builder 说起:重新拾起 Java 的 Lombok、注解与 Builder 模式
java
考虑考虑2 天前
Mybatis实现批量插入
java·后端·mybatis
咖啡八杯2 天前
GoF设计模式——中介者模式
java·后端·spring·设计模式
青石路2 天前
记一次多JDK版本问题的排查,一坑套一坑,差点没爬上来
java