Implementation Principles of RocketMQ Distributed Transaction Messages
The article explains how RocketMQ implements distributed transaction messages using a two‑phase commit model to ensure data consistency across micro‑service subsystems, detailing the workflow from half‑message production, broker handling, local transaction execution, commit/rollback decisions, and periodic status checks.
Using an e‑commerce order payment scenario, the article illustrates that a single user action often triggers changes in multiple downstream subsystems such as logistics, points, and shopping‑cart status. In a micro‑service architecture these subsystems communicate via RPC or message‑queue (MQ) components.
If RPC is used, the order flow becomes longer and requires distributed transactions for consistency, which degrades performance. When ordinary MQ messages are used, the message send and the local transaction cannot be guaranteed to be atomic, leading to problems such as successful message delivery while the local transaction fails, or network timeouts causing uncertainty about message delivery.
RocketMQ addresses these issues by providing distributed transaction messages that add a two‑phase commit capability on top of ordinary messages. This binds the second‑phase commit with the local transaction, ensuring global consistency.
The following steps describe the implementation flow (illustrated by the official RocketMQ‑5.0.0 source demo):
1. Producer sends a half‑transaction (prepared) message.
MessageAccessor.putProperty(msg, MessageConst.PROPERTY_TRANSACTION_PREPARED, "true");
MessageAccessor.putProperty(msg, MessageConst.PROPERTY_PRODUCER_GROUP, this.defaultMQProducer.getProducerGroup());The producer must set the transaction listener (TransactionListener) that contains the local transaction execution logic and the transaction status check logic.
2. Broker receives the half‑message, stores it as a special topic (RMQ_SYS_TRANS_HALF_TOPIC) with queue 0, and makes it invisible to consumers.
public static final String RMQ_SYS_TRANS_HALF_TOPIC = "RMQ_SYS_TRANS_HALF_TOPIC";3. After the local transaction finishes, the producer decides to commit, rollback, or mark the transaction as unknown.
If the half‑message was successfully stored, the producer may still encounter send failures; in that case the broker will later perform a status check.
4. Broker processes the commit/rollback request: it either deletes the half‑message or restores it to the original topic/queue, making the final message visible to consumers.
5. Broker periodically checks the transaction status of half‑messages that have not received a commit/rollback response. It invokes the producer’s TransactionListener#check method via a callback to any producer instance in the cluster.
org.apache.rocketmq.broker.transaction.queue.TransactionalMessageServiceImpl#check6. If the broker’s check attempts exceed the configured maximum (default 15), the half‑message is moved to the special topic TRANS_CHECK_MAXTIME_TOPIC for manual intervention.
long timeout = brokerController.getBrokerConfig().getTransactionTimeOut();
int checkMax = brokerController.getBrokerConfig().getTransactionCheckMax();
private int transactionCheckMax = 15;Monitoring this topic is essential; when necessary, operators should manually handle the stuck messages.
Summary : RocketMQ’s distributed transaction messages extend ordinary messages with a two‑phase commit mechanism, binding the global commit result with the local transaction. By storing half‑messages on the broker, performing periodic status checks, and providing configurable timeout and retry limits, RocketMQ ensures that the overall transaction outcome remains consistent even in the presence of network failures or partial successes.
Cognitive Technology Team
Cognitive Technology Team regularly delivers the latest IT news, original content, programming tutorials and experience sharing, with daily perks awaiting you.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.