RocketMQ源码分析之RocketMQ事务消息实现原理中篇----事务消息状态回查

本文深入探讨RocketMQ事务消息实现原理,重点分析`onWaitEnd()`方法中的事务状态回查逻辑。从获取配置参数到遍历消息队列,检查消息状态,以及事务超时判断,揭示了RocketMQ如何确保事务消息的正确处理。同时,文章还介绍了回查过程中涉及的关键类和方法,如`TransactionalMessageServiceImpl`的`check()`方法,以及异步发送回查消息的过程。
摘要由CSDN通过智能技术生成

protected void onWaitEnd() {

long timeout = brokerController.getBrokerConfig().getTransactionTimeOut(); // @1

int checkMax = brokerController.getBrokerConfig().getTransactionCheckMax(); // @2

long begin = System.currentTimeMillis();

log.info(“Begin to check prepare message, begin time:{}”, begin);

this.brokerController.getTransactionalMessageService().check(timeout, checkMax, this.brokerController.getTransactionalMessageCheckListener()); // @3

log.info(“End to check prepare message, consumed time:{}”, System.currentTimeMillis() - begin);

}

代码@1:从broker配置文件中获取transactionTimeOut参数值,表示事务的过期时间,一个消息的存储时间 + 该值 大于系统当前时间,才对该消息执行事务状态会查。

代码@2:从broker配置文件中获取transactionCheckMax参数值,表示事务的最大检测次数,如果超过检测次数,消息会默认为丢弃,即rollback消息。

接下来重点分析TransactionalMessageService#check的实现逻辑,其实现类:org.apache.rocketmq.broker.transaction.queue.TransactionalMessageServiceImpl

TransactionalMessageServiceImpl#check

String topic = MixAll.RMQ_SYS_TRANS_HALF_TOPIC;

Set msgQueues = transactionalMessageBridge.fetchMessageQueues(topic);

if (msgQueues == null || msgQueues.size() == 0) {

log.warn(“The queue of topic is empty :” + topic);

return;

}

step1:根据主题名称,获取该主题下所有的消息队列。

TransactionalMessageServiceImpl#check

for (MessageQueue messageQueue : msgQueues) {

// …

}

Step2:循环遍历消息队列,从单个消息消费队列去获取消息。

TransactionalMessageServiceImpl#check

long startTime = System.currentTimeMillis();

MessageQueue opQueue = getOpQueue(messageQueue);

long halfOffset = transactionalMessageBridge.fetchConsumeOffset(messageQueue);

long opOffset = transactionalMessageBridge.fetchConsumeOffset(opQueue);

log.info(“Before check, the queue={} msgOffset={} opOffset={}”, messageQueue, halfOffset, opOffset);

if (halfOffset < 0 || opOffset < 0) {

log.error(“MessageQueue: {} illegal offset read: {}, op offset: {},skip this queue”, messageQueue, halfOffset, opOffset);

continue;

}

Step3:获取对应的操作队列,其主题为:RMQ_SYS_TRANS_OP_HALF_TOPIC,然后获取操作队列的消费进度、待操作的消费队列的消费进度,如果任意一小于0,忽略该消息队列,继续处理下一个队列。

TransactionalMessageServiceImpl#check

List doneOpOffset = new ArrayList<>();

HashMap<Long, Long> removeMap = new HashMap<>();

PullResult pullResult = fillOpRemoveMap(removeMap, opQueue, opOffset, halfOffset, doneOpOffset);

if (null == pullResult) {

log.error(“The queue={} check msgOffset={} with opOffset={} failed, pullResult is null”,

messageQueue, halfOffset, opOffset);

continue;

}

Step4:调用fillOpRemoveMap主题填充removeMap、doneOpOffset数据结构,这里主要的目的是避免重复调用事务回查接口,这里说一下RMQ_SYS_TRANS_HALF_TOPIC、RMQ_SYS_TRANS

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值