RocketMQ源码分析----Consumer消费进度相关

本文深入探讨RocketMQ Consumer的消费进度管理,包括消费进度保存、持久化和提交过程。分析了Consumer和Broker如何处理消费进度,以及可能出现的重复消费问题。同时,介绍了Consumer和Broker的消费进度保存位置及持久化策略。
摘要由CSDN通过智能技术生成

在Consumer消费的时候总有几个疑问:

  • 消费完成后,这个消费进度存在哪里
  • 消费完成后,还没保存消费进度就挂了,会不会导致重复消费

Consumer

消费进度保存

消费完成后,会返回一个ConsumeConcurrentlyStatus.CONSUME_SUCCESS告诉MQ消费成功,以MessageListener的consumeMessage为入口分析。
消费的时候,是以ConsumeRequest类为Runnable对象,在线程池中进行处理的,即ConsumeRequest的run方法会处理这个状态

        @Override
        public void run() {
   

            //....
            status = listener.consumeMessage(Collections.unmodifiableList(msgs), context);
            // 如果这个ProcessQueue废弃了,则不处理
            if (!processQueue.isDropped()) {
   
                ConsumeMessageConcurrentlyService.this.processConsumeResult(status, context, this);
            }
        }

在消费完成后,将status交给processConsumeResult处理,代码如下

    public void processConsumeResult(//
                                     final ConsumeConcurrentlyStatus status, //
                                     final ConsumeConcurrentlyContext context, //
                                     final ConsumeRequest consumeRequest//
    ) {
   
         //....消费成功或者失败的处理
        
        // 将这批消息从ProcessQueue中移除,代表消费完毕,并返回当前ProcessQueue中的消息最小的offset
        long offset = consumeRequest.getProcessQueue().removeMessage(consumeRequest.getMsgs());
        if (offset >= 0 && !consumeRequest.getProcessQueue().isDropped()) {
   
            // 更新消费进度
            this.defaultMQPushConsumerImpl.getOffsetStore()
                .updateOffset(consumeRequest.getMessageQueue(), offset, true);
        }
    }

在分析ProcessQueue的时候,说过removeMessage返回有两种情况:

  1. 如果移除这批消息之后已经没有消息了,那么返回ProcessQueue中最大的offset+1
  2. 如果还有消息,那么返回treeMap中最小的key,即未消费的消息中最小的offset

getOffsetStore返回RemoteBrokerOffsetStore,看下其实现

    @Override
    public void updateOffset(MessageQueue mq, long offset, boolean increaseOnly) {
   
        if (mq != null) {
   
            // 通过MessageQueue获取本地的对应的消费进度
            AtomicLong offsetOld = this.offsetTable.get(mq);
            if (null == offsetOld) {
   
                offsetOld = this.offsetTable.putIfAbsent(mq, new AtomicLong(offset));
            }

            if (null != offsetOld) {
   
                //increaseOnly 为false则直接覆盖
                //increaseOnly为true则会判断更新的值比老的值大才会进行更新
                if (increaseOnly) {
   
                    MixAll.compareAndIncreaseOnly(offsetOld, offset);
                } else {
   
                    offsetOld.set(offset);
                }
            }
        }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值