Understanding RocketMQ: Basics, Ordered Messages, and Transactional Messages
This article provides a comprehensive overview of Apache RocketMQ, covering its core concepts, message models, reliability mechanisms, ordered message challenges and solutions, as well as detailed explanations of transactional messages, including implementation principles, producer and broker workflows, and practical considerations for ensuring consistency in distributed systems.
Introduction
Recently our team has accumulated practical experience with RocketMQ and wants to share the lessons learned. Because our company also uses a self‑developed message system (ZZMQ), we first introduce the open‑source version before comparing it with ZZMQ, hoping to help readers avoid common pitfalls.
Part 1: Basic Introduction
1. Domain Model Overview
Message Producer : The entity that creates messages in Apache RocketMQ, usually integrated into the upstream part of a business call chain. Producers are lightweight and anonymous.
1.1 Message Storage
Topic : A logical container in RocketMQ that groups queues; a topic consists of multiple queues and provides horizontal scalability.
MessageQueue : The physical storage unit inside a topic, similar to a partition in other MQ systems. Messages are stored in order within a queue.
Message : The smallest immutable transmission unit in RocketMQ.
1.2 Message Consumption
ConsumerGroup : An independent consumption identity that groups multiple consumers for load‑balancing and coordinated consumption.
Consumer : The downstream entity that pulls messages; each consumer must belong to a consumer group.
Subscription : Rules for message filtering, retry, and offset management, persisted on the broker.
2. Message Transmission Model
Most mainstream MQs support two transmission models: point‑to‑point (queue) and publish‑subscribe (topic).
Point‑to‑point features anonymous consumption and one‑to‑one communication.
Publish‑subscribe provides independent consumer identities and one‑to‑many communication. RocketMQ adopts the publish‑subscribe model.
3. Reliability of Normal Messages
3.1 Producer Reliability (ACK Mechanism)
RocketMQ uses an ACK mechanism to confirm that the broker has persisted the message.
3.2 Broker Reliability
The broker must handle various failure scenarios (normal shutdown, crash, OS crash, power loss, hardware failure, disk damage). Strategies include synchronous flushing for strong durability and asynchronous flushing for higher throughput, as well as master‑slave replication.
3.3 Consumer Reliability
ACK : Consumers acknowledge batches of messages, updating offsets.
Retry : Failed messages are retried up to 16 times with exponential back‑off; after that they are sent to a dead‑letter queue.
Dead‑letter Queue : Stores messages that could not be consumed after retries, allowing manual intervention.
Part 2: Ordered Messages
1. Online Issue Example
客服同学: @XXX 我们判责了,为啥客户还收不到退款? 售后单号xxxxxx。
研发同学: 让我看看。
…
研发同学: 问题原因: 历史代码,我们没有顺序消费消息,先判责完成,再打款. 这单先消费了打款消息,导致状态不对,打款失败。
研发同学: 为了保证消息的有序性,我等会把消息修改为顺序消费。2. Why Order Problems Occur
RocketMQ distributes messages of a topic across multiple queues. Because messages are spread, consumption order is not guaranteed unless all related messages are placed in the same queue.
3. Use Cases for Ordered Messages
Financial transactions and order processing where the first‑come‑first‑served rule is critical.
Real‑time data synchronization (e.g., database incremental sync) to maintain consistency.
4. Ensuring Order in Development
4.1 Producer Order
Single‑producer single‑thread guarantees order.
Multiple producers or multi‑threaded producers cannot guarantee global order; messages may interleave.
4.2 Consumer Order
Consumers must process messages strictly sequentially: receive → process → acknowledge before moving to the next message, avoiding asynchronous callbacks or parallel processing.
5. Precautions
Handle consumer exceptions carefully; infinite retries can block the queue. Implement a max‑retry limit and alert for manual intervention.
Distribute message keys to avoid hotspot queues; use hashing on business identifiers (e.g., order ID, user ID) to achieve balanced load while preserving order per key.
Part 3: Transactional Messages
1. Online Issue Example
客服同学: @XXX 用户在我们的app上一直获取不到报价,比较急,麻烦看一下怎么回事。
产品同学: 好的,收到,我这边马上找研发同学看一下,@XXX 需要帮忙看一下。
研发同学: 好的,我看一下。
…
研发同学: 询价过程中,风控命中了特殊报价池,我们把数据存到了数据库,同时发送了MQ消息,结果MQ成功但数据库失败,导致后续查询不到数据。
研发同学: 后续我们会把普通消息改成事务消息,保证消息发送和数据库存储的一致性。2. Why MQ Can Be Uncontrollable
MQ provides decoupling but does not guarantee that the sender’s and receiver’s state changes are consistent. Transactional messages are needed to bind the local transaction with the message send operation.
3. What Transactional Messages Solve
They ensure atomicity between the upstream operation and the downstream message, so either both succeed or both fail, solving distributed transaction problems.
4. Use Cases
Classic : Payment initiation where order status and external payment gateway calls must be consistent.
Our Scenario : After a dispute judgment, the result must be persisted locally and simultaneously notify downstream systems; transactional messages guarantee this consistency.
5. Need for Distributed Transactional Messages
MQ provides decoupling.
Distributed transaction ensures atomicity between local DB transaction and message send.
Final data consistency is achieved.
6. Open‑Source Transactional Message Implementation
6.1 Basic Principle
RocketMQ uses a “Half‑message” mechanism (similar to 2PC) where the producer first sends a half message, executes the local transaction, then sends a commit or rollback signal.
6.2 Producer Sending Logic
The producer sends a half message to RMQ_SYS_TRANS_HALF_TOPIC , performs the local transaction, and then sends a second‑phase message (commit/rollback) to RMQ_SYS_TRANS_OP_HALF_TOPIC . The broker only makes the message visible to consumers after a commit.
6.3 Broker Check‑Back Logic
If the broker does not receive a commit/rollback within a timeout, it initiates a check‑back to the producer (default up to 15 times) to determine the final state.
7. ZZMQ (Company‑Specific) Transactional Message
7.1 Differences
Open‑source version embeds transaction support directly into RocketMQ.
ZZMQ adds a horizontal abstraction layer, allowing transactional semantics on MQs that do not natively support them.
7.2 Implementation Details
Transactional information is persisted in a database; failed messages are placed into a time‑wheel queue for later retry. JVM memory considerations and service restarts are handled by persisting pending messages.
Conclusion
Both the open‑source and ZZMQ implementations of transactional messages are essential for ensuring consistency in modern distributed systems. Understanding their inner workings helps developers use them correctly and troubleshoot related issues.
Zhuanzhuan Tech
A platform for Zhuanzhuan R&D and industry peers to learn and exchange technology, regularly sharing frontline experience and cutting‑edge topics. We welcome practical discussions and sharing; contact waterystone with any questions.
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.