This topic introduces the concepts, scenarios, as well as usage precautions of MQ transactional messages.
- Transactional Message: MQ provides distributed transaction function which is similar to X/Open XA. You can achieve transaction consistency with transactional messages.
- Half Message: Refers to a message that cannot be delivered temporarily. When a message is successfully sent to the MQ server, but the server did not receive the second acknowledgement of the message from the producer, then the message is 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 acknowledgement of a transactional message. When MQ server finds that a message remains a half message for a long time, it will send a request to the message producer, checking the final status of the message (Commit or Rollback).
MQ transactional message can be applied in the following scenarios:
- Implement distributed transactions silimar to X/Open XA, and achieve transaction consistency.
The interaction process of MQ transactional message is shown below:
In the preceding figure:
- A sender sends a message to MQ server.
- MQ server sets the message to be persistent, and returns an ACK message to the sender. At this time, the message is a half message.
- The sender starts to execute local transaction logic.
- Based on the transaction execution result, the sender submits a secondary ACK message (Commit or Rollback) to MQ server. If the message state is Commit, MQ server marks the message as deliverable, and the consumer will receive this message. If it is Rollback, MQ server deletes the half message, and the consumer will not receive this message.
- In the case of network disconnection or application restart, the secondary ACK message submitted in step 4 will not reach MQ server. After a certain period of time, the MQ server initiates a message status check request.
- Upon receiving the status check request, the sender checks the local transaction execution result.
- Based on the final status of the local transaction, the sender submits a secondary ACK message again, and MQ server follows step 4 to process the half message.
Transactional message sending process includes step 1, 2, 3, and 4; and transactional message status check corresponds to step 5, 6, and 7.
Producer IDs of transactional messages cannot be shared with producer IDs of other types of messages. Unlike other types of message, transactional messages allow backward queries. MQ Server query clients by their Producer IDs.
The implementation class of LocalTransactionChecker has to be specified when creating 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, the following 3 status could be returned in the execute method:
- TransactionStatus.CommitTransaction: Submit a transaction to allow the consumer to consume the message.
- TransactionStatus.RollbackTransaction: Rolls back a transaction, and the message is discarded and will not be consumed.
- TransactionStatus.Unknown: The status cannot be determined yet, and MQ server is expected to send a request to the sender to check message status after a fixed period of time.
You can set the time to perform the first message status check for each message as follows:
Message message = new Message();
// Add the shortest time (s) for the first message status check in the message attribute. For the following setting, the actual first status check is done in 120~125 seconds.
// The method above only determines the shortest time for the first message status check, and the actual time to perform the check is usually 0~5 seconds after the specified time. If the transaction is not submitted after the first check, then the status check will be performed every 5 seconds.