[RocketMQ] Message reliability guarantee

In the actual use of RocketMQ, we cannot guarantee that every message sent will be successfully consumed by the consumer at one time. There may be situations in which multiple consumptions are required to succeed or consumption fails. What should Broker do?

1. Confirmation mechanism on the message consumer

RocketMQ provides an ack mechanism (manual ack by default) to ensure that messages can be consumed normally. In order to ensure that the message is definitely consumed successfully, RocketMQ will consider that the message is successfully consumed only if the user clearly indicates that the consumption is successful, and then delete the message. Power off in the middle, throwing an exception, etc. will not be considered as successful

DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("my_consumer_group");
consumer.registerMessageListener((MessageListenerConcurrently) (list, consumeOrderlyContext) -> {
    list.stream().forEach(messageExt -> System.out.println(new String(messageExt.getBody()))); 
    return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; // 签收,即手动ack
});

All consumers will provide a callback when setting up the monitor, and when the business realizes the consumption callback

  • When ConsumeConcurrentlyStatus.CONSUME_SUCCESS is returned in the callback method, RocketMQ will consider this batch of messages (the default is 1) to be consumed.
  • If message consumption fails at this time, such as database abnormality, insufficient balance, deduction failure, etc., all businesses think that the message needs to be retryed, as long as ConsumeConcurrentlyStatus.RECONSUME_LATER is returned, RocketMQ will think that this batch of message consumption has failed.

2. Attenuation of message retry

In order to ensure that the message is definitely consumed at least once, RocketMQ will re-send this batch of messages back to the broker, and after a certain delay (10 seconds by default, business can be set), they will be delivered to this ConsumerGroup again. And if this repeated consumption continues to fail to a certain number of times (default 16 times), it will be delivered to the DLQ dead letter queue.

Insert picture description here

The application can monitor the dead letter queue for manual intervention and can modify the broker-a.conf file

messageDelayLevel = 1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h

3. Retry message processing mechanism

Under normal circumstances, we do not need to retry 16 times in actual production, which is a waste of time and performance, and may cause message accumulation (only the previous confirmation is consumed, and the next message has a chance to be consumed). In theory, if the consumption fails when the number of repetition attempts reaches the result we want, then we need to record the corresponding message and end the repetition attempt

consumer.registerMessageListener((MessageListenerConcurrently) (list, consumeOrderlyContext) -> { 
    for (MessageExt messageExt : list) {  
        // 如果消息已经重发了3次
        if(messageExt.getReconsumeTimes()==3) {     
            // 可以将对应的数据保存到数据库,后续再做处理
            System.out.println(messageExt.getMsgId()+","+messageExt.getBody());    
            return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;  // 签收,结束重试   
        }   
    }   
    return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; 
});
  •  

Guess you like

Origin blog.csdn.net/qq_33762302/article/details/114859155