RocketMQ源码分析之消息ACK机制(消费进度)

本文详细分析了RocketMQ集群模式下消费进度的存储,特别是RemoteBrokerOffsetStore的updateOffset和readOffset方法,指出在并发消费场景下,通过TreeMap按消息offset排序确保消费进度的正确更新,同时探讨了这种方法可能引发的消息重复消费问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2.2集群模式消费进度存储(RemoteBrokerOffsetStore)

在阅读 RemoteBrokerOffsetStore 之前,我们先思考一下如下的问题:

在集群模式下,多个消费者会负载到不同的消费队列上,因为消息消费进度是基于消息队列进行保存的,也就是不同的消费者之间的消费进度保存是不会存在并发的,但是在同一个消费者,非顺序消息消费时,一个消费者(多个线程)并发消费消息,比如m1 < m2,,但m2先消费完,此时是如何保存的消费进度呢?举个例子,如果m2的offset为5,而m1的offset为4,如果m2先消费完,保存进度为5,那m1消息消费完,保存进度为4,这样岂不乱来了,该如何处理呢?

2.2.1 RemoteBrokerOffsetStore 核心属性

private final static Logger log = ClientLogger.getLog();
// MQ客户端实例,该实例被同一个客户端的消费者、生产者共用
private final MQClientInstance mQClientFactory;  
// MQ消费组    
private final String groupName;
// 消费进度存储(内存中)                                 
private ConcurrentMap<MessageQueue, AtomicLong> offsetTable =
        new ConcurrentHashMap<MessageQueue, AtomicLong>();    
// 构造方法
public RemoteBrokerOffsetStore(MQClientInstance mQClientFactory, String groupName) {   
    this.mQClientFactory = mQClientFactory;
    this.groupName = groupName;

有了广播模式,本地消息消费进度保存等基本认识之后,我们重点来关注 RemoteBrokerOffsetStore 核心方法。

2.2.2 updateOffset

@Override
    public void updateOffset(MessageQueue mq, long offset, boolean increaseOnly) {
        if (mq != null) {
            AtomicLong offsetOld = this.offsetTable.get(mq);
            if (null == offsetOld) {     // 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值