Spring整合RocketMQ(四)

事务消息

RocketMQ在4.3版本后已经支持了分布式事务消息了

RocketMQ采用了两阶段提交(2PC)的思想来实现了事务消息,同时增加一个补偿逻辑来处理二阶段超时或者失败的消息

事务消息的流程

1、生产者发送一条事务消息,这条消息在发送后不会立即送到用户指定的topic中,而是将其发送到主题为RMQ_SYS_TRANS_HALF_TOPIC的主题中,这样消费者就不会收到这条消息去处理了

2、接着就看用户的本地事务执行情况

成功

发送commit请求,rocketmq就会把这条放在RMQ_SYS_TRANS_HALF_TOPIC主题中的消息放到用户指定的topic中

消费者就可以收到这条消息并处理了

正常失败

发送rollback请求,rocketmq就会把这条消息丢弃

超时失败

rocketmq会主动询问生产者,主动进行事务状态回查,默认回查15次,如果都失败,则直接回滚这条消息


只有在确保该消息事务被生产者提交成功后才会向broker发送消息,从而被消费者获取并进行消费

事务状态

  • LocalTransactionState.COMMIT_MESSAGE:事务已提交,消费者可消费
  • LocalTransactionState.ROLLBACK_MESSAGE:回滚事务,这条消息会被删除,不允许被消费者消费
  • LocalTransactionState.UNKNOW:中间状态,它代表需要检查消息队列来确定状态

流程图

在这里插入图片描述
在这里插入图片描述

案例说明

上个案例中普通的DefaultMQProducer是不支持发送事务消息的

所以我们把MQProducer的实现换一下

@Bean
public TransactionMQProducer transactionMQProducer() {
    TransactionMQProducer transactionMQProducer = new TransactionMQProducer(rocketMqProducerProperties.getGroupName());
    transactionMQProducer.setNamesrvAddr(rocketMqProducerProperties.getNamesrvAddr());
    transactionMQProducer.setMaxMessageSize(rocketMqProducerProperties.getMaxMessageSize());
    transactionMQProducer.setSendMsgTimeout(rocketMqProducerProperties.getSendMsgTimeout());
    transactionMQProducer.setRetryTimesWhenSendFailed(rocketMqProducerProperties.getRetryTimesWhenSendFailed());
    // 这里就是差别
    // 注册了一个事务监听器
    transactionMQProducer.setTransactionListener(new TransactionListener() {
        /**
        * 发送半消息成功后,执行本地事务
        */
        @Override
        public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
            System.out.println("执行本地事务");
            return msg.getBody().length == 0 ? LocalTransactionState.ROLLBACK_MESSAGE : LocalTransactionState.COMMIT_MESSAGE;
        }
        /**
        * 检查本地事务是否成功
        */
        @Override
        public LocalTransactionState checkLocalTransaction(MessageExt msg) {
            System.out.println("超时询问");
            return LocalTransactionState.ROLLBACK_MESSAGE;
        }
    });
    try {
        transactionMQProducer.start();
        log.info("transaction producer starts successfully !, groupName: {} ,namesrvAddr:{}", rocketMqProducerProperties.getGroupName(), rocketMqProducerProperties.getNamesrvAddr());
    } catch (MQClientException e) {
        e.printStackTrace();
        log.info("transaction producer starts failure !, groupName: {} ,namesrvAddr:{}", rocketMqProducerProperties.getGroupName(), rocketMqProducerProperties.getNamesrvAddr());
    }
    return transactionMQProducer;
}

面试题

1.RocketMQ发送事务消息的流程

生产者先向broker发送一条半消息,这个消息是对用户不可见的

broker收到半消息后会先将这条消息放到事务相关队列中

接着告诉生产者执行本地事务executeLocalTransaction

生产者执行本地事务成功则向broker发送commit消息让broker提交,将消息从事务消息队列中取出放到生产者指定的topic中

生产者执行本地事务失败则向broker发送rollback消息让broker回滚,将消息从事务消息队列中删除

由于生产者故障或者网络波动导致生产者的本地事务执行情况长时间没有通知broker

则broker会主动询问生产者本地事务执行情况checkLocalTransaction

如果是因为生产者故障,则broker会在失败一定次数后执行rollback操作

消费者一直监听topic

只有当事务消息被提交后,才会被放到生产者指定的topic中,这个时候消费者才会收到这条消息,执行本地的逻辑开始处理

2.RocketMQ的事务消息是如何保证数据的最终一致性的

RocketMQ的事务消息是分布式事务方案中使用可靠消息最终一致性

是BASE理论的体现,强调的是最终一致性

生产者这边先通过half消息和本地事务保证了数据的一致性

消费者不断从topic中取出消息去处理,如果处理失败就重试,重试次数过多就会告警交由人工处理

3.生产者本地事务执行成功,由于网络原因导致commit消息没有被broker接收到,broker回查事务的时候由于生产者宕机或者网络原因,多次尝试超时后回滚了事务消息,这种情况怎么办

这个问题是我想出来的,我不知道出现这种情况怎么办😭

大佬们会这道题的评论区留言

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Spring框架提供了多种方式来集成RocketMQ。首先,可以将消息生产者和消费者定义成bean对象,交由Spring容器管理。其次,可以使用RocketMQ的外部项目rocketmq-jms通过spring-jms方式进行集成。第三种方式是对于基于spring-boot的应用,可以使用RocketMQ的外部项目rocketmq-spring-boot-starter来方便地收发消息。 具体来说,rocketmq-jms项目实现了JMS 1.1规范的部分内容,目前支持JMS中的发布/订阅模型收发消息。而rocketmq-spring-boot-starter项目则支持同步发送、异步发送、单向发送、顺序消费、并行消费、集群消费、广播消费等特性。 以上是Spring整合RocketMQ的基本信息。具体的实现步骤,可以参考引用内容中的说明。在基本知识的基础上,通过4个简单的步骤即可实现Spring Boot与RocketMQ整合。这些不同的集成方式可以根据项目需求和个人喜好进行选择和使用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Spring整合RocketMQ](https://blog.csdn.net/u010277958/article/details/88634423)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [SpringBoot整合RocketMQ,老鸟们都是这么玩的!](https://blog.csdn.net/jianzhang11/article/details/130073300)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芝麻\n

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值