- 如何处理第二阶段的失败消息?
在本地事务执行完成后会向MQServer发送Commit或Rollback操作,此时如果在发送消息的时候生产者出故障了,那么要保证这条消息最终被消费,MQServer会像服务端发送回查请求,确认本地事务的执行状态。
当然了rocketmq并不会无休止的的信息事务状态回查,默认回查15次,如果15次回查还是无法得知事务状态,RocketMQ默认回滚该消息。
- 消息状态
事务消息有三种状态:
TransactionStatus.CommitTransaction:提交事务消息,消费者可以消费此消息
TransactionStatus.RollbackTransaction: 回滚事务,它代表该消息将被删除,不允许被消费。
TransactionStatus.Unknown :中间状态,它代表需要检查消息队列来确定状态。
业务需求:用户请求订单微服务 order-service
接口删除订单(退货),删除订单时需要调用 account-service
的方法给账户增加余额,一个典型的分布式事务问题。
基础配置
在开始代码之前首先需要搭建好的RocketMQ环境,如果有不会的可以参考下面这篇文章:
http://javadaily.cn/articles/2020/04/07/1586248405351.html 非常详细
- 在Order-Service和Account-Service中引入Rocket消息组件
org.apache.rocketmq
rocketmq-spring-boot-starter
- 在配置中心添加RocketMQ的相关配置
rocketmq:
name-server: xxx.xx.x.xx:9876
producer:
group: cloud-group
- 在OrderService服务中建立一张事务日志表rocketmq_transaction_log(作用稍后说)
发送半消息
Order-Service作为分布式事务开始的入口,在Service层我们给RocketMQ发送一条半消息
- OrderController入口
/**
-
根据订单号删除订单
-
@param orderNo 订单编号
*/
@PostMapping(“/order/delete”)
public ResultData delete(@RequestParam String orderNo){
log.info(“delete order id is {}”,orderNo);
orderService.delete(orderNo);
return ResultData.success(“订单删除成功”);
}
直接调用orderService的delete方法
- OrderServiceImpl业务逻辑
@Override
public void delete(String orderNo) {
Order order = orderMapper.selectByNo(orderNo);
//如果订单存在且状态为有效,进行业务处理
if (