RocketMQ源码分析----ProcessQueue

本文探讨RocketMQ中的关键数据结构ProcessQueue,它作为消息消费快照,存储消费进度和消息。内容涉及isLockExpired、isPullExpired、cleanExpiredMsg等核心功能,以及在顺序和并发消费模式下的作用。ProcessQueue在负载均衡、消费进度管理和消息拉取等方面发挥关键作用。

RockerMQ里有个非常重要的数据结构叫ProcessQueue,很多功能,例如消费进度,消费等等功能的底层核心数据保存都是有ProcessQueue提供,下面介绍一下ProcessQueue提供的功能,而整个涉及的流程不会在这展开,在另外的功能分析文章如果涉及才会深入分析

看下代码上的注释:

Queue consumption snapshot

即消息快照的意思,为什么要这样形容呢?主要是因为在消息拉取到的时候,会把消息存放在其中。另外在拉取消息的时候,使用是的PullRequest去请求,其内部结构如下:

public class PullRequest {
   
   
    private String consumerGroup;
    private MessageQueue messageQueue;
    private ProcessQueue processQueue;
    private long nextOffset;
    private boolean lockedFirst = false;
}

可以看到,ProcessQueue和一个MessageQueue是对应的,即一个队列会有一个ProcessQueue的数据结构,看下其主要的字段

public class ProcessQueue {
   
   
    public final static long RebalanceLockMaxLiveTime =
            Long.parseLong(System.getProperty("rocketmq.client.rebalance.lockMaxLiveTime", "30000"));
    public final static long RebalanceLockInterval = Long.parseLong(System.getProperty("rocketmq.client.rebalance.lockInterval", "20000"));
    private final static long PullMaxIdleTime = Long.parseLong(System.getProperty("rocketmq.client.pull.pullMaxIdleTime", "120000"));
    // 用来保存拉取到的消息
    private final TreeMap<Long, MessageExt> msgTreeMap = new TreeMap<Long, MessageExt>();
    // 当前保存的消息数,放进来的时候会加,移除的时候会减
    private final AtomicLong msgCount = new AtomicLong();
    // 消费锁,主要在顺序消费和移除ProcessQueue的时候使用
    private final Lock lockConsume = new ReentrantLock();
    // 顺序消费的时候使用
    private final TreeMap<Long, MessageExt> msgTreeMapTemp = new TreeMap<Long, MessageExt>();
    // 记录了废弃ProcessQueue的时候lockConsume的次数
    private final AtomicLong tryUnlockTimes = new AtomicLong(0);
    // ProcessQueue中保存的消息里的最大offset,为ConsumeQueue的offset
    private volatile long queueOffsetMax = 0L;
    // 该数据结构里的消息是否废弃
    private volatile boolean dropped = false;
    // 上次执行拉取消息的时间
    private volatile long lastPullTimestamp = System.currentTimeMillis();
    // 上次消费完消息后记录的时间
    private volatile long lastConsumeTimestamp = System.currentTimeMillis();
    
    private volatile boolean locked = false;
    // 上次锁定的时间
    private volatile long lastLockTimestamp = System.currentTimeMillis();
    // 是否正在消息
    private volatile boolean consuming = false;
    // 该参数为调整线程池的时候提供了数据参考
    private volatile long msgAccCnt = 0;
}

isLockExpired

    public boolean isLockExpired() {
   
   
        boolean result = (System.currentTimeMillis() - this.lastLockTimestamp) > RebalanceLockMaxLiveTime;
        return result;
    }

顺序消费的时候使用,消费之前会判断一下ProcessQueue锁定时间是否超过阈值(默认30000ms),如果没有超时,代表还是持有锁,具体细节在顺序消费的时候会详细说明.
负载

isPullExpired

    public boolean isPullExpired() {
   
   
        boolean result = (System.currentTimeMillis() - this.lastPullTimestamp) > PullMaxIdleTime;
        return result;
    }

在拉取的时候更新lastPullTimestamp的值,然后在rebalance的时候会去判断ProcessQueue已经超过一定的时间没有去拉取消息,如果是的话,则将ProcessQueue废弃(setDropped(true))且从ProcessQueue和MessageQueue的对应关系中移除该ProcessQueue,代码细节如下:

if (pq.isPullExpired()) {
   
   
    switch (this.consumeType()) {
   
   
        case CONSUME_ACTIVELY:
            break;
        case CONSUME_PASSIVELY:
            pq.setDropped(true);
            if (this.removeUnnecessaryMessageQueue(mq, pq)) {
   
   
                it.remove();
                changed = true;
                log.error("[BUG]doRebalance, {}, remove unnecessary mq, {}, because pull is pause, so try to fixed it",
                        consumerGroup, mq);
            }
            break;
        default:
            break;<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值