RocketMQ系列之事务消息

事务这个概念和内容这里就不提了哈,我们这里直接看RocketMQ怎么实现事务消息的,如果真的对事务不了解的,可以看一下这篇:

分布式事务系列之入门_阿小冰的博客-CSDN博客_分布式事务分布式事务系列之入门https://blog.csdn.net/qq_38377525/article/details/123159026


事务消息发送和消费

下面的架子是按照之前的一个框架继续开发的,有必要的话,可以参考一下:

RocketMQ系列之消息发送/消费初体验_阿小冰的博客-CSDN博客RocketMQ系列之消息发送/消费初体验https://blog.csdn.net/qq_38377525/article/details/123253718 1、发送创建订单的事务消息,预下单操作

这里定义一个订单的实体类Order,包含订单ID、订单标题两个属性即可

编写事务的模拟接口,代码如下:

@RestController
public class TransactionalController {
    @Autowired
    private Source source;

    @GetMapping("/transactional")
    public String tramsactional(){
        Order order=new Order("1","上海浦东");
        String transactionId=UUID.randomUUID().toString();
        MessageBuilder builder = MessageBuilder.withPayload(order).setHeader(RocketMQHeaders.TRANSACTION_ID,transactionId);
        Message message=builder.build();
        source.output().send(message);
        return "order is ok";
    }
}

2、配置文件

server.port=8070

spring.cloud.stream.rocketmq.binder.name-server=127.0.0.1:9876
spring.cloud.stream.bindings.output.destination=TopicTest
spring.cloud.stream.rocketmq.bindings.output.producer.group=producer-demo-group

3、创建事务监听器

@RocketMQTransactionListener(txProducerGroup = "OrderTransactionGroup")
public class TransactionMsgListener implements RocketMQLocalTransactionListener {
    //在发送消息后调用,用于执行本地事务,如果本地事务执行成功,RocketMQ 再提交消息
    //生产者发送消息给MQ后,MQ会回调这个方法,我们在该方法中编写事务逻辑,执行成功后MQ会将消息提                          
    //交,然后用下面的checkLocalTransaction方法来验证事务是否全部执行成功
    @Override
    public RocketMQLocalTransactionState executeLocalTransaction(Message message, Object o) {
        try {
            //获取前面订单生成的事务id
            String transactionId=(String)message.getHeaders().get(RocketMQHeaders.TRANSACTION_ID);
            //以事务ID为主键,执行本地事务
            Order order=(Order) message.getPayload();
            boolean result = this.saveOrder(order, transactionId);
            return result?RocketMQLocalTransactionState.COMMIT:RocketMQLocalTransactionState.ROLLBACK;
        }catch (Exception e) {
            return RocketMQLocalTransactionState.ROLLBACK;
        }
    }

    //用于检查事务是否执行成功,RocketMQ依赖此方法做补偿
    @Override
    public RocketMQLocalTransactionState checkLocalTransaction(Message message) {
        //获取事务ID
        String transactionId=(String)message.getHeaders().get(RocketMQHeaders.TRANSACTION_ID);
        //以事务ID为主键,查询本地事务执行情况
        if(isSuccess(transactionId)){
            return RocketMQLocalTransactionState.COMMIT;
        }
        return RocketMQLocalTransactionState.ROLLBACK;
    }

    /**
     * @Description: 将事务ID设置为唯一主键,调用数据库insert
     */
    private boolean saveOrder(Order order,String transactionId){
        return true;
    }

    /**
     * @Description: 查询数据库
     */
    private boolean isSuccess(String transactionId){
        return true;
    }
}

使用@RocketMQTransactionListener注解用于接收本地事务的监听,txProducerGroup是事务组名称,和前面定义的OrderTransactionGroup保持一致,其中这个接口还有两个实现方法,也在上面的代码有所体现

  • executeLocalTransaction:执行本地事务,在消息发送成功会回调执行,一单事务提交成功,下游应用的消费者就能收到该消息
  • checkLocalTransaction:检查本地事务执行状态,如果executeLocalTransaction方法中返回的状态是位置UNKNOWN或者为返回的状态,就会默认在预处理发送的一分钟后由Broker通知Producer检查本地事务,在Producer中回调本地事务监听器中的checkLocalTransaction方法,检查本地事务时,可以根据事务ID查询本地事务的状态,再返回具体事务状态给Broker

4、消费者不变,和上面提供链接中的消费者保持一致即可,然后启动验证即可


事务消息的底层原理

RocketMQ采用的2PC的方案,第一阶段生产者向Broker发送预处理消息,此时消息其实还没有投递出去,这个时候消费者还不能消费,第二阶段生产向Broker发送提交或回滚消息,具体流程如下:

  • 发送预处理消息成功后,开始执行本地事务
  • 如果本地事务执行成功,发送提交请求提交事务消息,消息会投递给消费者

 

  • 如果本地事务执行失败,发送回滚请求回滚事务消息,消息不会投递给消费者,看上图

 

  •  如果本地事务状态未知,因为网络故障或者生产者挂掉了,Broker没有收到二次确认的相关信息,就会由Broker端发送请求向生产者进行回查,询问并确认提交还是回滚,如果状态一直都是未确认,那就需要人工干预程序了,看上图
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值