How to Prevent Message Loss in RocketMQ: Scenarios and Zero‑Loss Solutions
This article examines common RocketMQ message loss scenarios—including network glitches, asynchronous disk flushing, and consumer acknowledgment failures—and presents practical solutions such as transactional messaging, synchronous flush configuration, and proper consumer handling to achieve zero message loss.
When using a message queue like RocketMQ in a project, especially in financial transaction scenarios, preventing message loss is critical.
Message loss scenarios in RocketMQ
The basic consumption flow involves three steps, each of which can lead to loss:
Producer sends a message to RocketMQ.
RocketMQ receives the message and must persist it to disk; otherwise power loss or broker crash can cause loss.
Consumer retrieves the message and, after successful processing, the flow ends.
The following diagrams illustrate these steps and the points where loss can occur.
Ensuring zero message loss
Scenario 1 – Network or communication glitches : Use RocketMQ’s built‑in transaction mechanism.
Producer sends a half message; consumers cannot read it.
If the half message fails to send, execute rollback logic.
When the half message is successfully sent and the broker returns success, the producer proceeds with its core business logic.
If the core logic fails, roll back and ask the broker to delete the half message.
If the core logic succeeds, send a commit request so the consumer can read the message.
Scenario 2 – Asynchronous disk flushing or disk failure : Change the broker’s flush policy to synchronous flushing (set flushDiskType=SYNCHRONOUS_FLUSH) and deploy RocketMQ in a master‑slave cluster so that data is replicated across followers.
With synchronous flush, a successful response guarantees that the message is persisted to disk; replication protects against disk damage.
Scenario 3 – Consumer acknowledgment issues : Ensure the consumer only acknowledges after the message is fully processed.
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
// Process the message
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});If the consumer crashes before returning CONSUME_SUCCESS, RocketMQ will treat the consumer as failed and re‑deliver the message to another consumer, preventing loss.
Avoid spawning separate threads to process messages asynchronously and then immediately returning success, as this can cause the broker to think the message is consumed while it is still being processed.
Trade‑offs
Transactional messaging adds many extra steps and reduces performance.
Synchronous flushing is slower than asynchronous flushing by an order of magnitude.
Master‑slave replication introduces additional latency for data synchronization.
Consumers must wait for processing to finish before acknowledging, which can lower throughput.
Zero message loss is a double‑edged sword; the appropriate solution should be chosen based on the specific business requirements.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
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.
