All Products
Search
Document Center

ApsaraMQ for RocketMQ:Ordered messages

Last Updated:Feb 28, 2024

Ordered messages are a type of featured message in ApsaraMQ for RocketMQ. This topic describes the common scenarios, working mechanism, limits, and usage notes of ordered messages.

Common scenarios

Heterogeneous systems use status synchronization to maintain strong consistency in scenarios such as ordered event processing, transaction matchmaking, and real-time incremental data synchronization. The preceding scenarios require ordered delivery of messages from upstream applications to downstream applications when an event change occurs. ApsaraMQ for RocketMQ provides ordered messages to help you implement ordered message transmission.

Scenario 1: Transaction matchmaking

交易撮合

For example, in securities and stock trading scenarios, if multiple bidders offer the same bid price for a bid order, the bidder who first offers the bid price wins the bid. Therefore, the downstream order processing system must be designed to process orders in the order in which prices were offered.

Scenario 2: Real-time incremental data synchronization

Figure 1. Normal messages普通消息

Figure 2. Ordered messages顺序消息

For example, you want to perform incremental synchronization of data that is related to database modifications. You can use ordered messages in ApsaraMQ for RocketMQ to transmit messages from the upstream source database to the downstream query system. The messages can be binary logs of addition, deletion, and modification operations. The downstream system retrieves the messages in the order in which the messages are sent to make the database status updated in the same order. Ordered messages help you ensure consistency between the operations in the upstream system and the status data in the downstream system. If you use normal messages in this scenario, status inconsistency may occur.

Working mechanism

What is an ordered message?

Ordered messages are a type of featured message in ApsaraMQ for RocketMQ. Ordered messages are delivered to consumers in the order in which the messages are sent. This type of message allows you to implement ordered processing in business scenarios.

Compared with other types of messages, ordered messages are characterized by the order of message sending, storage, and delivery.

ApsaraMQ for RocketMQ uses message groups to identify the order of ordered messages. Before you send ordered messages, you must specify the message group to which each message belongs.

Important

Only messages of the same message group are processed in first in, first out (FIFO) order. The order of messages that belong to different message groups or do not belong to any message group is not ensured.

ApsaraMQ for RocketMQ ensures the processing order of messages in message groups. You can divide messages into different groups based on message consumption logic. This helps improve system concurrency and throughput while ensuring message processing order for specific workloads.

How to maintain the order of messages

The order of messages in ApsaraMQ for RocketMQ is maintained in the production and consumption stages.

  • Production order: ApsaraMQ for RocketMQ uses a protocol that is established between the producer and the broker to ensure that messages are serially sent from the producer to the broker and that the messages are stored and persisted in the same order as they are sent.

    To ensure the production order of messages, make sure that the following conditions are met:

    • Same message group

      The production order takes effect only for messages that belong to the same message group. The production order of messages that belong to different message groups or do not belong to any message group is not ensured. Before you send ordered messages, you can configure a message group for each message.

    • Single producer

      The production order takes effect only for messages that are produced by a single producer. ApsaraMQ for RocketMQ cannot determine the order of messages from different producers in different systems, regardless of whether the same message group is specified for the messages.

    • Serial transmission

      Producers in ApsaraMQ for RocketMQ support secure access from multiple threads. If a producer uses multiple threads to concurrently send messages, the system cannot determine the order of messages from different threads.

    After a producer that meets the preceding conditions sends messages to ApsaraMQ for RocketMQ, the system ensures that messages from the same message group are stored in the same queue based on the order in which the messages are sent. The following figure describes how ordered messages are stored in ApsaraMQ for RocketMQ brokers.顺序存储逻辑

    • ApsaraMQ for RocketMQ stores messages from the same message group in the same queue based on the order in which the messages are sent.

    • ApsaraMQ for RocketMQ can store messages from different message groups in the same queue, but not necessarily in the order in which the messages are sent.

    In the preceding figure, messages from MessageGroup 1 and MessageGroup 4 are stored in MessageQueue 1. ApsaraMQ for RocketMQ ensures that messages G1-M1, G1-M2, and G1-M3 from MessageGroup 1 are stored in the queue in the same order as they are sent. Messages G4-M1 and G4-M2 from MessageGroup 4 are also stored in the order in which the messages are sent. However, messages from MessageGroup 1 and MessageGroup 4 are stored in no particular order.

  • Consumption order: ApsaraMQ for RocketMQ uses a protocol that is established between the consumer and the broker to ensure that messages are consumed in the same order in which the messages are stored.

    To ensure the consumption order of messages, make sure that the following conditions are met:

    • Delivery order

      ApsaraMQ for RocketMQ ensures that messages are delivered in the same order in which they are stored by using a client SDK and the communications protocol of the broker. When consumer applications consume messages, the applications must follow the receive-process-acknowledge process to prevent messages from being out of order due to asynchronous consumption.

      Important

      If a consumer is of the Push type, ApsaraMQ for RocketMQ ensures that the messages are delivered to the consumer one by one in the order in which they are stored. If a consumer is of the Simple type, multiple messages may be pulled at a time by the consumer. In this case, the consumption order of the messages is implemented by the business application. For information about consumer types, see Consumer types.

    • Limited retries

      ApsaraMQ for RocketMQ limits the number of retries that failed ordered messages can perform. If a message fails to be delivered after the maximum number of retries is reached, ApsaraMQ for RocketMQ skips the message and continues consuming the subsequent messages. This prevents failed messages from constantly blocking message processing.

      In scenarios in which the consumption order is critical, we recommend that you specify an appropriate number of retries to prevent unordered message processing.

Combination of production order and consumption order

If you want messages to be processed in FIFO order, the production order and consumption order of the messages must be ensured. In most business scenarios, a producer may map to multiple consumers, but not all consumers require ordered message consumption. You can use flexible combinations of the production order and consumption order in different business scenarios. For example, you can send ordered messages but concurrently consume the messages to improve throughput. The following table describes different combinations of the production order and the consumption order.

Production order

Consumption order

Effect

Ordered

Ordered

The order of messages in the same message group is ensured.

Messages in the same message group are sent and consumed in the same order.

Ordered

Concurrent

Messages are concurrently and chronologically consumed.

Unordered

Ordered

The order of messages that are stored in the same queue is ensured.

ApsaraMQ for RocketMQ only ensures that messages are consumed in the same order as the are stored in a queue.

Unordered

Concurrent

Messages are concurrently and chronologically consumed.

Lifecycle of an ordered message

生命周期

  • Initialization

    The message is built and initialized by the producer and is ready to be sent to a broker.

  • Pending consumption

    The message is sent to the broker and is visible and available to the consumer.

  • Being consumed

    The message is obtained by the consumer and processed based on the local consumption logic of the consumer.

    In this process, the broker waits for the consumer to return the consumption result. If no response is received from the consumer in a specific period of time, ApsaraMQ for RocketMQ performs retries on the message. For more information, see Consumption retry.

  • Consumption commit

    The consumer completes the consumption and commits the consumption result to the broker. The broker marks whether the current message is consumed.

    By default, ApsaraMQ for RocketMQ retains all messages. When the consumption result is committed, the message is marked as consumed instead of being immediately deleted. Messages are deleted only if the retention period expires or the system has insufficient storage space. Before a message is deleted, the consumer can re-consume the message.

  • Message deletion

    If the retention period of message expires or the storage space is insufficient, ApsaraMQ for RocketMQ deletes the earliest stored messages from the physical file in a rolling manner. For more information, see Message storage and cleanup.

Important
  • Message consumption failures or timeouts trigger the retry logic on a broker. If consumption retry is triggered for a message, the message reaches the end of its lifecycle. The message is retried as a new message with a new message ID.

  • If consumption retry is triggered for an ordered message, the subsequent messages can be processed only after the ordered message is processed.

Limits

Only topics whose MessageType is set to FIFO can be used to send and receive ordered messages.

Examples

Different from normal messages, ordered messages must have message groups specified for them. We recommend that you configure message groups at a fine-grained level based on your business requirements to allow for workload decoupling and concurrency scaling.

The following sample code provides an example on how to send and receive ordered messages in Java.

For information about the complete sample code, see Apache RocketMQ 5.x SDKs (recommended).

        // Send an ordered message. 
        MessageBuilder messageBuilder = null;
        Message message = messageBuilder.setTopic("topic")
                // The message key. The system can use the key to locate the message. 
                .setKeys("messageKey")
                // The message tag. The consumer can use the tag to filter messages. 
                .setTag("messageTag")
                // Specify a message group. We recommend that you do not include a large number of messages in the group. 
                .setMessageGroup("fifoGroup001")
                // The message body. 
                .setBody("messageBody".getBytes())
                .build();
        try {
            // Send the message. You must take note of the sending result and capture exceptions such as failures.
            SendReceipt sendReceipt = producer.send(message);
            System.out.println(sendReceipt.getMessageId());
        } catch (ClientException e) {
            e.printStackTrace();
        }
        // Make sure that ordered delivery is applied to the consumer group. Otherwise, messages are delivered concurrently and in no particular order. 
        // Consumption example 1: If the consumer is of the Push type, the consumer needs to only process messages in the message listener. 
        MessageListener messageListener = new MessageListener() {
            @Override
            public ConsumeResult consume(MessageView messageView) {
                System.out.println(messageView);
                // Return the status based on the consumption result. 
                return ConsumeResult.SUCCESS;
            }
        };
        // Consumption example 2: If the consumer is of the Simple type, the consumer must actively obtain messages for consumption and commit the consumption results. 
        // Note: If the consumption of a message in a message group is not complete, the next message in the message group cannot be retrieved if you call the Receive function. 
        List<MessageView> messageViewList = null;
        try {
            messageViewList = simpleConsumer.receive(10, Duration.ofSeconds(30));
            messageViewList.forEach(messageView -> {
                System.out.println(messageView);
                // After consumption is complete, you must invoke ACK to commit the consumption result. 
                try {
                    simpleConsumer.ack(messageView);
                } catch (ClientException e) {
                    e.printStackTrace();
                }
            });
        } catch (ClientException e) {
            // If the message fails to be pulled due to throttling or other reasons, you must re-initiate the request to obtain the message. 
            e.printStackTrace();
        }

Obtain consumption retry logs of ordered messages

If ordered messages are consumed in Push mode, the messages are retried on the consumer client and the broker cannot obtain the details of the retry logs. If the delivery result displayed in the trace of an ordered message indicates that the message delivery failed, you must check the information about the maximum number of retries and the consumer client in the consumer client logs.

For information about the log path of a consumer client, see Log configuration.

You can search the following keywords to query the information about consumption failures in client logs:

Message listener raised an exception while consuming messages
Failed to consume fifo message finally, run out of attempt times

Usage notes

Use serial consumption to prevent out-of-order message processing

We recommend that you use serial message consumption instead of batch consumption. Consumption of multiple messages at the same time may cause out-of-order message processing.

For example, messages 1, 2, 3, and 4 are sent in the 1-2-3-4 order and the order of batch consumption is 1-[2, 3](processed in batches but failed)-[2, 3](retry)-4. The system may repeatedly process Message 2 if Message 3 fails to be processed. As a result, messages are consumed out of order.

Avoid including a large number of messages in a message group

ApsaraMQ for RocketMQ ensures that messages in the same message group are stored in the same queue. A message group that contains a large number of messages causes the corresponding queue to be overloaded. This affects messaging performance and hinders scalability. When you configure message groups, you can use order IDs and user IDs as the message sequencing conditions. This ensures the order of messages of the same end user.

We recommend that you split messages in your business applications by message group. For example, in a scenario in which you do not need to ensure the order of messages of different users, you can use order IDs and user IDs as message group keywords to implement ordered processing of messages of the same end user.