13. Consumer-消费进度管理

不管是顺序消费还是并发消费,在一批消息消费完成后都会将消息从processQueue中移除,返回最小processQueue的最小偏移量,并更新消费进度。

广播模式下,消费进度文件存储在各个消费端本地,因为多个消费端是同时消费的,且互相独立的。

集群模式下,多个消费端共同消费同一个队列,且同一时间只有一个消费端在消费,所以消费进度文件是存储在broker的。

 

消费进度管理接口是:OffsetStore

 

广播模式下,实现类是LocalFileOffsetStore

集群模式下,实现类是RemoteBrokerOffsetStore

 

这里主要看下集群模式下的进度管理,消费消费完后的逻辑为

ConsumeMessageConcurrentlyService.processConsumeResult方法:

       
。。。
 long offset = consumeRequest.getProcessQueue().removeMessage(consumeRequest.getMsgs());
        if (offset >= 0 && !consumeRequest.getProcessQueue().isDropped()) {
            this.defaultMQPushConsumerImpl.getOffsetStore().updateOffset(consumeRequest.getMessageQueue(), offset, true);
        }

调用updateOffset方法更新消息进度

 

RemoteBrokerOffsetStore.updateOffset方法:

    public void updateOffset(MessageQueue mq, long offset, boolean increaseOnly) {
        if (mq != null) {
            AtomicLong offsetOld = this.offsetTable.get(mq);
            if (null == offsetOld) {
                offsetOld = this.offsetTable.putIfAbsent(mq, new AtomicLong(offset));
            }

            if (null != offsetOld) {
                if (increaseOnly) {
                    MixAll.compareAndIncreaseOnly(offsetOld, offset);
                } else {
                    offsetOld.set(offset);
                }
            }
        }
    }

offsetTable是一个ConcurrentMap<MessageQueue, AtomicLong>,记录每个队列的进度,这里只是更新进度到内存中。

同步进度到broker在persistAll方法中处理

 

RemoteBrokerOffsetStore.persistAll方法:

    public void persistAll(Set<MessageQueue> mqs) {
        if (null == mqs || mqs.isEmpty())
            return;

        final HashSet<MessageQueue> unusedMQ = new HashSet<MessageQueue>();
        if (!mqs.isEmpty()) {
            for (Map.Entry<MessageQueue, AtomicLong> entry : this.offsetTable.entrySet()) {
                MessageQueue mq = entry.getKey();
                AtomicLong offset = entry.getValue();
                if (offset != null) {
                    if (mqs.contains(mq)) {
                        try {
                            this.updateConsumeOffsetToBroker(mq, offset.get());
                            log.info("[persistAll] Group: {} ClientId: {} updateConsumeOffsetToBroker {} {}",
                                this.groupName,
                                this.mQClientFactory.getClientId(),
                                mq,
                                offset.get());
                        } catch (Exception e) {
                            log.error("updateConsumeOffsetToBroker exception, " + mq.toString(), e);
                        }
                    } else {
                        unusedMQ.add(mq);
                    }
                }
            }
        }

        if (!unusedMQ.isEmpty()) {
            for (MessageQueue mq : unusedMQ) {
                this.offsetTable.remove(mq);
                log.info("remove unused mq, {}, {}", mq, this.groupName);
            }
        }
    }

很简单就是一个循环遍历所有队列,然后同步到broker中。

 

 

那么什么时候调用这个方法同步到broker呢?

MQClientInstance启动时候会启动一些调度任务其中就包括定期同步进度,每10s定时同步所有队列的消费进度到broker中

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值