RocketMQ事务消息

RocketMQ事务消息
最新回答
洛小汐

2023-12-17 09:10:40

RocketMQ事务消息详解

Apache RocketMQ在4.3.0版中引入了分布式事务消息的支持,它采用了2PC(Two-Phase Commit,两阶段提交)的思想来实现事务消息的提交,并增加了一个补偿逻辑来处理二阶段超时或失败的消息。

一、RocketMQ事务消息流程概要

RocketMQ事务消息的大致方案分为两个流程:正常事务消息的发送及提交、事务消息的补偿流程。

  1. 事务消息发送及提交

    (1) 发送消息(half消息):首先,生产者向RocketMQ发送一个half消息,这个half消息在初始状态下对消费者是不可见的。

    (2) 服务端响应消息写入结果:RocketMQ服务端接收到half消息后,会响应消息写入的结果。

    (3) 执行本地事务:生产者根据服务端返回的写入结果来执行本地事务。如果写入失败,则half消息对业务不可见,本地事务逻辑不执行。

    (4) Commit或Rollback:根据本地事务的执行状态,生产者向RocketMQ发送Commit或Rollback操作。Commit操作会生成消息索引,使消息对消费者可见;Rollback操作则不会生成索引,消息保持不可见状态。

  2. 补偿流程

    (1) 回查:对于处于pending状态(即未确定Commit或Rollback的事务消息),RocketMQ服务端会发起一次回查请求到生产者端。

    (2) 检查本地事务状态:生产者收到回查请求后,检查对应本地事务的状态。

    (3) 重新Commit或Rollback:根据本地事务的状态,生产者重新执行Commit或Rollback操作。

二、RocketMQ事务消息设计

  1. 事务消息在一阶段对用户不可见

    RocketMQ事务消息的主要特点是,一阶段发送的消息对用户是不可见的。这是通过改变half消息的主题来实现的。half消息被写入到一个特殊的主题RMQ_SYS_TRANS_HALF_TOPIC中,由于消费组未订阅该主题,因此消费端无法消费这些half消息。RocketMQ会开启一个定时任务,从该主题中拉取消息进行消费,并根据生产者组发送回查事务状态请求,根据事务状态来决定是提交或回滚消息。

  2. Commit和Rollback操作以及Op消息的引入

    在完成一阶段写入一条对用户不可见的消息后,二阶段如果是Commit操作,则需要让消息对用户可见;如果是Rollback则需要撤销一阶段的消息(实际上是通过Op消息来标识事务的最终状态)。RocketMQ引入了Op消息的概念,用Op消息来标识事务消息已经确定的状态(Commit或Rollback)。无论事务消息是Commit还是Rollback,都会记录一个Op操作。Commit操作在写入Op消息前会创建Half消息的索引。

  3. Op消息的存储和对应关系

    Op消息被写入到一个全局特定的Topic中,这个Topic是内部的,不会被用户消费。Op消息的内容为对应的Half消息的存储Offset,这样通过Op消息能索引到Half消息进行后续的回查操作。

  4. Half消息的索引构建

    在执行二阶段Commit操作时,需要构建出Half消息的索引。一阶段的Half消息由于写到了一个特殊的Topic,所以二阶段构建索引时需要读取出Half消息,并将Topic和Queue替换成真正的目标Topic和Queue,之后通过一次普通消息的写入操作来生成一条对用户可见的消息。

  5. 处理二阶段失败的消息

    如果在RocketMQ事务消息的二阶段过程中失败了,例如在做Commit操作时出现网络问题导致Commit失败,那么RocketMQ会采用补偿机制,即“回查”。Broker端对未确定状态的消息发起回查,将消息发送到对应的Producer端(同一个Group的Producer),由Producer根据消息来检查本地事务的状态,进而执行Commit或Rollback。RocketMQ默认回查15次,如果15次回查还是无法得知事务状态,RocketMQ默认回滚该消息。

三、总结

RocketMQ事务消息通过2PC思想和补偿逻辑,实现了分布式事务消息的一致性。它采用了一系列设计策略,如改变half消息的主题、引入Op消息来标识事务的最终状态、构建Half消息的索引等,来确保事务消息的正确性和可靠性。同时,RocketMQ还提供了回查机制来处理二阶段失败的消息,进一步增强了事务消息的健壮性。