Message queue RocketMQ: message retry

Article catalog

Message queue RocketMQ: (I) overview

Message queuing RocketMQ: (II) system architecture

Message queue RocketMQ: (III) sending ordinary messages (three methods)

Message queue RocketMQ: (IV) sequential messages

Message queue RocketMQ: (V) delay message

Message queue RocketMQ: (VII) batch messages

Message queue RocketMQ: (VIII) message filtering

7, Message sending retry

Producer's mechanism for resending failed messages is called message sending retry mechanism, also known as message re delivery mechanism.

For message re delivery, you should pay attention to the following points:

  1. If the producer sends messages synchronously or asynchronously, the sending failure will be retried, but there is no retry mechanism for the sending failure of oneway message
  2. Only ordinary messages have a send retry mechanism, and sequential messages do not
  3. The message re delivery mechanism can ensure that the message is sent successfully and not lost as much as possible, but it may cause message duplication. Message duplication does not occur under normal circumstances. When there is a large amount of messages and network jitter, message duplication will become a probability event

There are three strategies for message sending retry: synchronous sending failure strategy, asynchronous sending failure strategy and message disk brushing failure strategy

1. Synchronous sending failure policy

For ordinary messages, the round robin strategy is adopted by default to select the queue to send messages. If the sending fails, it will retry 2 times by default. However, when retrying, the Broker that failed to send last time will not be selected, but other brokers will be selected.

    DefaultMQProducer producer = new DefaultMQProducer("pg"); 
    producer.setNamesrvAddr("rocketmqOS:9876"); 
    // Set the number of times to retry sending when synchronous sending fails. The default is 2 times 
    producer.setRetryTimesWhenSendFailed(3); 
    // Set the sending timeout to 5s, and the default is 3s 
    producer.setSendMsgTimeout(5000);

If the number of retries exceeds, an exception will be thrown, and the Producer will ensure that the message is not lost.

When RemotingException, MQClientException and MQBrokerException occur in the Producer, the Producer will automatically resend the message.

2. Asynchronous send failure policy

When the asynchronous sending fails to retry, the asynchronous retry will not select other brokers, but only retry on the current Broker, so this policy cannot guarantee that the message will not be lost.

    DefaultMQProducer producer = new DefaultMQProducer("pg"); 
    producer.setNamesrvAddr("rocketmqOS:9876"); 
    // Specifies that no retry sending will be performed after asynchronous sending fails 
    producer.setRetryTimesWhenSendAsyncFailed(0);

3. Message disk brushing failure policy

Message swiping timeout (Master, Slave). By default, messages will not be sent to other brokers. For important messages, you can enable it by setting the retryAnotherBrokerWhenNotStoreOK property to true in the Broker's configuration file.

8, Message consumption retry

After the consumer fails to consume a message, the message will be re delivered according to the message retry mechanism. If the message has not been successfully consumed after reaching the retry times, the message will be put into the dead letter queue.

No matter how many times a message is retried, the Message ID of these retried messages will not change

1. Retry consumption of sequential messages

Sequential message: after the Consumer fails to consume the message, in order to ensure the order of the message, it will automatically retry the message continuously until the consumption is successful. The default interval between consumption retries is 1000ms. During retry, the application will be blocked in message consumption.

    DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("cg"); 
    // The consumption retry time interval of sequential message consumption failure, in milliseconds, the default is 1000, and its value range is [10, 30000] 
    consumer.setSuspendCurrentQueueTimeMillis(100);

Since the retry of sequential messages is endless and uninterrupted until the consumption is successful, for the consumption of sequential messages, it is important to ensure that the application can timely monitor and handle the consumption failure, so as to avoid permanent blocking of consumption.

Note: the sequence message does not have a send failure retry mechanism, but has a consumption failure retry mechanism

2. Consumption retry of unordered messages

For unordered messages (normal messages, delayed messages, transaction messages), when the Consumer fails to consume messages, the message retry effect can be achieved by setting the return status.

Note: the retry of unordered messages only takes effect for the cluster consumption mode; The broadcast consumption mode does not provide failure retry feature, that is, after consumption fails, the failure message will not be retried and new messages will continue to be consumed.

For retry consumption under disordered message cluster consumption, each message is allowed to be retried up to 16 times by default. If the message still fails after 16 retries, the message will be delivered to the dead letter queue. The message retry interval is as follows:

retry countTime between last retryretry countTime between last retry
110 seconds97 minutes
230 seconds108 minutes
31 minute119 minutes
42 minutes1210 minutes
53 minutes1320 minutes
64 minutes1430 Minutes
75 minutes151 hour
86 minutes162 hours

If a message fails to consume all the time, it will be retried 16 times in the next 4 hours and 46 minutes. Beyond this time range, the message will not be retried and will be delivered to the dead letter queue.

Modify consumption retry times:

	DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("cg"); 
	// Modify consumption retry times 
	consumer.setMaxReconsumeTimes(10);

3. Maximum number of retries for custom messages

Allow the maximum number of retries to be set when the Consumer starts. The retry interval will follow the following policy:

  • If the maximum number of retries is less than or equal to 16, the retry interval is described in the table above
  • The maximum number of retries is more than 16, and the retry interval of more than 16 times is 2 hours each time
  • The setting of the maximum number of message retries is valid for all Consumer instances under the same Group ID
  • If only one of the two Consumer instances under the same Group ID is set, the configuration will take effect for both Consumer instances
  • The configuration takes effect by overwriting, that is, the last started Consumer instance will overwrite the configuration of the previously started instance

4. Consumption retry configuration

In the cluster consumption mode, if the message consumption fails and the message is expected to be retried later, it needs to be explicitly configured in the implementation of the message listener interface (choose one of the three methods):

  1. Return consumeconcurrantlystatus RECONSUME_ Later (recommended)
  2. Return Null
  3. Throw exception
consumer.registerMessageListener(new MessageListenerConcurrently() {
    @Override
    public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
                                                    ConsumeConcurrentlyContext context) {
        //The message processing logic throws an exception and the message will be retried.
        doConsumeMessage(message);
        
        //Method 1: return action Reconsumelater, the message will be retried.
        return ConsumeConcurrentlyStatus.RECONSUME_LATER;
        //Method 2: return null and the message will be retried.
        return null;
        //Method 3: throw an exception directly and the message will be retried.
        throw new RuntimeException("Consumer Message exception");
    }
});

5. Consumption does not retry configuration

In the cluster consumption mode, if the message fails, it is expected that the message will not be retried. You need to catch the exceptions that may be thrown in the consumption logic and finally return consumeconcurrentystatus CONSUME_ Success, this message will not be retried after that.

consumer.registerMessageListener(new MessageListenerConcurrently() {
    @Override
    public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
                                                    ConsumeConcurrentlyContext context) {
        try {
            doConsumeMessage(message);
        } catch (Throwable e) {
        	//Catch all exceptions in the consumption logic and return consumeconcurrantlystatus CONSUME_ SUCCESS
            return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
        }

        //The message processing is normal, and the consumption success is returned directly
        return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
    }
});

6. Get message retries

After receiving the message, the consumer can obtain the number of retries of the message in the following ways:

@Override
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,
                                                ConsumeConcurrentlyContext context) {
    for (MessageExt msg : msgs) {
	    //Gets the number of retries for the message.
	    System.out.println(msg.getReconsumeTimes());
    }
    
    return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}

9, Dead letter queue

When the first consumption of a message fails, the message queue will automatically retry the consumption; After reaching the maximum number of retries, if the consumption still fails, it indicates that the consumer cannot correctly consume the message under normal circumstances. At this time, the message queue will not immediately discard the message, but send it to the special queue corresponding to the consumer.

Under normal circumstances, messages that cannot be consumed are called dead letter messages, and the special queue for storing dead letter messages is called dead letter queue.

1. Dead letter message features

  • It will no longer be consumed normally by consumers
  • The validity period is the same as the normal message, which is 3 days. It will be deleted automatically after 3 days

2. Dead letter queue feature

  • A dead letter queue corresponds to a Group ID instead of a single consumer instance. Name is% DLQ%consumerGroup@consumerGroup
  • If a Group ID does not produce a dead letter message, the corresponding dead letter queue will not be created
  • A dead letter queue contains all dead letter messages generated by the corresponding Group ID, no matter which Topic the message belongs to

Keywords: Java Back-end Distribution queue RocketMQ

Added by jrtaylor on Fri, 24 Dec 2021 15:20:41 +0200