RocketMQ的重复消费问题

      最近同事在调试环境中遇到了RocketMQ的重复消费问题,邀请我去解决下。

     先谈谈这个问题的背景,关于RocketMQ的重复消费结合官方和大家的使用经验,我们有这样的一个认知:

Exactly Only Once

(1). 发送消息阶段,不允许发送重复的消息。

(2). 消费消息阶段,不允许消费重复的消息。

只有以上两个条件都满足情况下,才能认为消息是“Exactly Only Once”,而要实现以上两点,在分布式系统环境下,不可避免要产生巨大的开销。所以RocketMQ为了追求高性能,并不保证此特性,要求在业务上进行去重,也就是说消费消息要做到幂等性。RocketMQ虽然不能严格保证不重复,但是正常情况下很少会出现重复发送、消费情况,只有网络异常,Consumer启停等异常情况下会出现消息重复。

此问题的本质原因是网络调用存在不确定性,即既不成功也不失败的第三种状态,所以才产生了消息重复性问题。

带着这样的认知我着重于查看调试环境的网络状况。

RocketMQ中,消息消费者在消费消息时可能会遇到异常,这时候可以根据业务需求配置消息的重试机制。消息的重试次数可以在消费者的代码中进行设置,以确保消息在处理失败时能够有足够多次的机会再次被消费。 以下是一个简单的示例,展示如何在Java代码中配置RocketMQ消费者的消息重试消费次数: ```java import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer; import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext; import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus; import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently; import org.apache.rocketmq.client.exception.MQClientException; import org.apache.rocketmq.common.message.MessageExt; import java.util.List; public class Consumer { public static void main(String[] args) throws MQClientException { // 创建消费者 DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("consumerGroup"); // 设置NameServer地址 consumer.setNamesrvAddr("127.0.0.1:9876"); // 订阅主题 consumer.subscribe("topicTest", "*"); // 设置消息监听器,并实现自定义的消息处理逻辑 consumer.setMessageListener(new MessageListenerConcurrently() { @Override public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs, ConsumeConcurrentlyContext context) { // 确保在业务处理过程中捕获异常 try { // 处理消息的逻辑代码 // ... // 返回消息处理状态,此处表示处理成功 return ConsumeConcurrentlyStatus.CONSUME_SUCCESS; } catch (Exception e) { // 如果处理消息时发生异常,则可以返回RECONSUME_LATER状态,进行重试 return ConsumeConcurrentlyStatus.RECONSUME_LATER; } } }); // 启动消费者 consumer.start(); System.out.println("Consumer Started."); } } ``` 在上面的代码中,我们设置了一个消息监听器,如果在消息处理过程中出现异常,我们捕获这些异常并返回`ConsumeConcurrentlyStatus.RECONSUME_LATER`状态,这样RocketMQ会将这条消息重新放回队列,以便后续重新消费。默认情况下,RocketMQ会重试多次,但具体次数可以在消费者配置中设置。 要设置重试消费的次数,可以在消费者的配置中设置`messageModel`和`maxReconsumeTimes`属性: ```java // 创建消费者配置 ConsumerConfig consumerConfig = new ConsumerConfig(); // 设置为集群消费模式(负载均衡) consumerConfig.setMessageModel(MessageModel.CLUSTERING); // 设置最大重试次数,超过该次数后消息会被死信队列处理,或者根据配置决定是否丢弃 consumerConfig.setMaxReconsumeTimes(16); ``` 需要注意的是,在实际应用中,通常还需要结合死信队列(Dead Letter Queue)来处理那些经过多次重试仍然失败的消息。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值