rocketmq源码解析之管理请求获取最大的offset

说在前面

本次继续解析管理请求,GET_MAX_OFFSET 获取最大的offset,更多源码解析请关注“天河聊架构”微信公众号

源码解析
进入到这个方法org.apache.rocketmq.broker.processor.AdminBrokerProcessor#getMaxOffset获取最大的offset

private RemotingCommand getMaxOffset(ChannelHandlerContext ctx,
        RemotingCommand request) throws RemotingCommandException {
        final RemotingCommand response = RemotingCommand.createResponseCommand(GetMaxOffsetResponseHeader.class);
        final GetMaxOffsetResponseHeader responseHeader = (GetMaxOffsetResponseHeader) response.readCustomHeader();
        final GetMaxOffsetRequestHeader requestHeader =
            (GetMaxOffsetRequestHeader) request.decodeCommandCustomHeader(GetMaxOffsetRequestHeader.class);
//        根据topic和queueId获取最大的offset =》
        long offset = this.brokerController.getMessageStore().getMaxOffsetInQueue(requestHeader.getTopic(), requestHeader.getQueueId());
        responseHeader.setOffset(offset);
        response.setCode(ResponseCode.SUCCESS);
        response.setRemark(null);
        return response;
    }

进入这个方法org.apache.rocketmq.store.DefaultMessageStore#getMaxOffsetInQueue 根据topic和queueId获取最大的offset

public long getMaxOffsetInQueue(String topic, int queueId) {
//        根据topic和queueId找到消费者队列=》
        ConsumeQueue logic = this.findConsumeQueue(topic, queueId);
        if (logic != null) {
//            获取最大的offset =》
            long offset = logic.getMaxOffsetInQueue();
            return offset;
        }

//        如果不存在指定topic和queueId的消费队列直接返回0
        return 0;
    }

进入这个方法org.apache.rocketmq.store.DefaultMessageStore#findConsumeQueue 根据topic和queueId查询消费队列

public ConsumeQueue findConsumeQueue(String topic, int queueId) {
        ConcurrentMap<Integer, ConsumeQueue> map = consumeQueueTable.get(topic);
        if (null == map) {
            ConcurrentMap<Integer, ConsumeQueue> newMap = new ConcurrentHashMap<Integer, ConsumeQueue>(128);
            ConcurrentMap<Integer, ConsumeQueue> oldMap = consumeQueueTable.putIfAbsent(topic, newMap);
            if (oldMap != null) {
                map = oldMap;
            } else {
                map = newMap;
            }
        }

//        按queue id查找消费者队列
        ConsumeQueue logic = map.get(queueId);
        if (null == logic) {
            ConsumeQueue newLogic = new ConsumeQueue(
                topic,
                queueId,
//                消费者队列存储地址 user.home/store/consumequeue
                StorePathConfigHelper.getStorePathConsumeQueue(this.messageStoreConfig.getStorePathRootDir()),
//                每个文件存储默认30W
                this.getMessageStoreConfig().getMapedFileSizeConsumeQueue(),
                this);
            ConsumeQueue oldLogic = map.putIfAbsent(queueId, newLogic);
            if (oldLogic != null) {
                logic = oldLogic;
            } else {
                logic = newLogic;
            }
        }

        return logic;
    }

往上返回到这个方法org.apache.rocketmq.store.ConsumeQueue#getMaxOffsetInQueue 查询最大的offset

public long getMaxOffsetInQueue() {
//        =》
        return this.mappedFileQueue.getMaxOffset() / CQ_STORE_UNIT_SIZE;
    }

进入这个方法org.apache.rocketmq.store.MappedFileQueue#getMaxOffset

public long getMaxOffset() {
//        获取存储映射文件队列中索引位置最大的映射文件
        MappedFile mappedFile = getLastMappedFile();
        if (mappedFile != null) {
//            映射文件的起始offset+映射文件的可读取的索引位置
            return mappedFile.getFileFromOffset() + mappedFile.getReadPosition();
        }
//        如果队列中没有存储映射文件直接返回0
        return 0;
    }

进入这个方法org.apache.rocketmq.store.MappedFileQueue#getLastMappedFile() 获取映射文件集合中最后一个映射文件

public MappedFile getLastMappedFile() {
    MappedFile mappedFileLast = null;
    while (!this.mappedFiles.isEmpty()) {
        try {
            mappedFileLast = this.mappedFiles.get(this.mappedFiles.size() - 1);
            break;
        } catch (IndexOutOfBoundsException e) {
            //continue;
        } catch (Exception e) {
            log.error("getLastMappedFile has exception.", e);
            break;
        }
    }

    return mappedFileLast;
}

可以看到映射文件集合是用CopyOnWriteArrayList实现

//    并发线程安全队列存储映射文件
    private final CopyOnWriteArrayList<MappedFile> mappedFiles = new CopyOnWriteArrayList<MappedFile>();

往上返回到这个方法org.apache.rocketmq.broker.processor.AdminBrokerProcessor#getMaxOffset结束

说在最后

本次解析仅代表个人观点,仅供参考。

加入技术微信群
在这里插入图片描述

钉钉技术群
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值