Keep RocketMQ Messages Consistent with MySQL Transactions in Spring
Writing business data to MySQL and publishing a message are two separate operations. A crash between them can leave the database and message system inconsistent.
RocketMQ transactional messages use a half-message workflow:
- The producer sends a prepared message.
- RocketMQ asks the producer to execute the local database transaction.
- The producer commits or rolls back the message according to the local result.
- If the result is unknown, the broker calls the producer's transaction-check listener.
The check must query durable business state rather than process memory. Store a transaction or event record in the same MySQL transaction as the business change.
Consumers must be idempotent because retries and duplicate delivery are normal. Use a unique business key, processed-message table, or state transition that rejects repeated application. Acknowledge only after the local consumer transaction commits.
Monitor unresolved half messages, check failures, retry counts, dead-letter queues, and end-to-end lag. Transactional messaging improves eventual consistency but does not remove the need for reconciliation jobs and operational recovery procedures.