This topic introduces the concepts, scenarios, and precautions of Message Queue for Apache RocketMQ transactional messages.
- Transactional message: Message Queue for Apache RocketMQ provides a distributed transaction processing function similar to X/Open XA to ensure transaction consistency in Message Queue for Apache RocketMQ.
- Half message: A half message is a message that cannot be delivered temporarily. When a message is successfully sent to the Message Queue for Apache RocketMQ broker, but the broker does not receive the second acknowledgment of the message from the producer, the message is then marked as "temporarily undeliverable". The message in this status is called a half message.
- Message status check: Network disconnection or producer application restart may result in the loss of the second acknowledgment for a transactional message. When the Message Queue for Apache RocketMQ broker finds that a message remains as a half message for a long time, it will send a request to the message producer to check the final status of the message (Commit or Rollback).
Transactional messages can be applied in the following scenarios:
In the process of placing an order through the shopping cart, the user entry is the shopping cart system, and the transaction order entry is the transaction system. Final consistency must be ensured between the two systems. In this case, transactional messages can be used for processing. After an order is placed, the transaction system sends a transaction order message to Message Queue for Apache RocketMQ. The shopping cart system subscribes to the transaction order message of Message Queue for Apache RocketMQ, performs corresponding business processing, and updates the shopping cart data.
The procedure for sending a transactional message is as follows:
- A producer sends a half message to the Message Queue for Apache RocketMQ broker.
- The Message Queue for Apache RocketMQ broker sets the message to be persistent and returns an ACK message to the producer. At this time, the message is a half message.
- The producer starts to execute the local transaction logic.
- Based on the transaction execution result, the producer submits a secondary ACK message (Commit or Rollback) to the Message Queue for Apache RocketMQ broker. If the message state is Commit, the broker marks the message as deliverable, and the consumer will receive this message. If the message state is Rollback, the broker deletes the half message, and the consumer will not receive this message.
The procedure for checking the transactional message status is as follows:
- In the case of network disconnection or application restart, the secondary ACK message submitted in Step 4 will not reach the RocketMQ broker. After a certain period of time, the Message Queue for Apache RocketMQ broker initiates a message status check request.
- Upon receiving the status check request, the producer checks the final execution result of the local transaction.
- Based on the retrieved final status of the local transaction, the producer submits a secondary ACK message again, and the Message Queue for Apache RocketMQ broker follows Step 4 to process the half message.
- Group IDs of transactional messages cannot be shared with group IDs of messages of other types. Unlike messages of other types, transactional messages allow status checking. The Message Queue for Apache RocketMQ broker can query the message status on clients by group ID.
- You must specify the implementation class of
LocalTransactionCheckerwhen creating the producer of a transactional message through
ONSFactory.createTransactionProducer, so that message status check can be performed when exceptions occur.
- When the transactional message is sent to execute the local transaction, any of the following three statuses may be returned in the
TransactionStatus.CommitTransaction:The transaction is submitted, and the consumer can consume the message.
TransactionStatus.RollbackTransaction:The transaction is rolled back, and the message is discarded and cannot be consumed.
TransactionStatus.Unknow:The status cannot be determined, and the Message Queue for Apache RocketMQ broker is expected to send a request to the producer to check the message status after a fixed period of time.
- You can set the shortest time for the initial message status check for each message as follows:
Message message = new Message(); //Add the shortest time in seconds for the initial message status check in the message attribute. For the following setting, the initial status check is done in 120 to 125 seconds: message.putUserProperties(PropertyKeyConst.CheckImmunityTimeInSeconds,"120"); //The preceding method determines only the shortest time for the initial message status check, and the actual time to perform the check usually floats backward 0 to 5 seconds. If the transaction is not submitted after the initial message status check, subsequent status checks will be performed every 5 seconds.
The sample code for sending transactional messages is as follows: