提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
Spring Rocketmq 事务消息 RocketMQTemplate的使用
一、事务消息的执行流程图
1、第一阶段本地会将消息提交到rocketmq服务器上,这里的rocketmq服务器我的理解是broker代理服务器。
2、第二阶段就是服务器接受消息成功返回装填
3、第三阶段就是进入半提交状态,执行本地事务,本地事务的逻辑就是在如下代理类中处理
@RocketMQTransactionListener
@Service
public class TransactionMsgListener implements RocketMQLocalTransactionListener {
@Override
public RocketMQLocalTransactionState executeLocalTransaction(Message message, Object arg) {
//TODO 开启本地事务(实际就是我们的jdbc操作)
//TODO 执行业务代码(例如插入订单数据库表等)
//TODO 提交或回滚本地事务
//模拟一个处理结果
int index = 8;
/**
* 模拟返回事务状态
*/
switch (index) {
case 1:
//处理业务
String jsonStr = new String((byte[]) message.getPayload(), StandardCharsets.UTF_8);
System.out.println("本地事务回滚,回滚消息," + jsonStr);
//返回ROLLBACK状态的消息会被丢弃
return RocketMQLocalTransactionState.ROLLBACK;
case 3:
//返回UNKNOW状态的消息会等待Broker进行事务状态回查
return RocketMQLocalTransactionState.UNKNOWN;
default:
System.out.println("事务提交,消息正常处理");
//返回COMMIT状态的消息会立即被消费者消费到
return RocketMQLocalTransactionState.COMMIT;
}
}
@Override
public RocketMQLocalTransactionState checkLocalTransaction(Message message) {
String jsonStr = new String((byte[]) message.getPayload(), StandardCharsets.UTF_8);
System.out.println("调用回查本地事务接口:" + jsonStr);
return RocketMQLocalTransactionState.COMMIT;
}
}
executeLocalTransaction方法中就是事务的逻辑。
4、本地给broker代理服务器发送消息,回滚还是提交。
5、如果没有收到步骤四的消息确认,此时是半提交状态,会进入步骤6,进行消息回查,在上例代码中的checkLocalTransaction()方法装载的是回查的逻辑。
2、使用代码
/**
* 事务消息示例
*
* @param message
* @return
*/
@Override
public String sendMessageTranstion(String message) {
//创建队列 MessageQueue 队列不要设置太大,默认值为4
rocketMQTemplate.getProducer().setDefaultTopicQueueNums(4);
Message info = MessageBuilder.withPayload(message + (i++)).build();
//发送事务消息:采用的是sendMessageInTransaction方法,返回结果为TransactionSendResult对象,该对象中包含了事务发送的状态、本地事务执行的状态等
//参数一:验证topic 为null即可
//参数二:topic 如果想添加tag,可以使用"topic:tag"的写法
//参数三:消息内容
//参数四:
TransactionSendResult result = rocketMQTemplate.sendMessageInTransaction(null, "MQ_TOPIC", info, null);
//发送状态
String sendStatus = result.getSendStatus().name();
//本地事务执行状态
String localState = result.getLocalTransactionState().name();
System.out.println("发送状态:" + sendStatus + ";本地事务执行状态" + localState);
return null;
}
3、总结
1、事务消息的出现是rocketmq的特点,因为其他消息中间件没有。
2、事务消息的逻辑需要自己处理,需要较强的编码能力。