RocketMQ源码分析(十四)之IndexFile

本文详细分析了RocketMQ的IndexFile结构,包括构造函数、putKey过程及查找机制。同时介绍了IndexService的主要功能,如定时创建索引和提供索引操作接口。内容涵盖IndexFile的Slot设计、冲突解决策略以及IndexService的查询实现。
摘要由CSDN通过智能技术生成

版本

  1. 基于rocketmq-all-4.3.1版本

IndexFile

  1. IndexFile(索引文件)由IndexHeader(索引文件头), Slot(槽位)和Index(消息的索引内容)三部分构成。对于每个IndexFile来说IndexHeader是固定大小的,Slot是索引的目录,用于定位Index在IndexFile中存储的物理位置

  2. 存储图
    在这里插入图片描述

  3. slot总数系统默认500W个,slot中放的是最新index的位置,因为一般查询的时候肯定是优先查最近的消息,每个slot中放的位置值是索引在indexFile中的偏移量

  4. IndexFile属性

    //hash槽大小
    private static int hashSlotSize = 4;
    //index大小
    private static int indexSize = 20;
    private static int invalidIndex = 0;
    /**
     * 槽位,默认500w个
     * 配置参见org.apache.rocketmq.store.config.MessageStoreConfig#maxHashSlotNum
     */
    private final int hashSlotNum;
    /**
     * 默认2000w
     * 配置参见org.apache.rocketmq.store.config.MessageStoreConfig#maxIndexNum
     */
    private final int indexNum;
    private final MappedFile mappedFile;
    private final FileChannel fileChannel;
    private final MappedByteBuffer mappedByteBuffer;
    private final IndexHeader indexHeader;
    
  5. IndexHeader属性

    public static final int INDEX_HEADER_SIZE = 40;
    
    private static int beginTimestampIndex = 0;
    private static int endTimestampIndex = 8;
    private static int beginPhyoffsetIndex = 16;
    private static int endPhyoffsetIndex = 24;
    private static int hashSlotcountIndex = 32;
    private static int indexCountIndex = 36;
    private final ByteBuffer byteBuffer;
    //第一个索引消息落在Broker的时间戳
    private AtomicLong beginTimestamp = new AtomicLong(0);
    //最后一个索引消息落在Broker的时间戳
    private AtomicLong endTimestamp = new AtomicLong(0);
    //第一个索引消息在commitlog的物理偏移量
    private AtomicLong beginPhyOffset = new AtomicLong(0);
    //最后一个索引消息在commitlog的物理偏移量
    private AtomicLong endPhyOffset = new AtomicLong(0);
    //构建索引占用的槽位数
    private AtomicInteger hashSlotCount = new AtomicInteger(0);
    //构建的索引个数
    private AtomicInteger indexCount = new AtomicInteger(1);
    

构造函数

  1. 构造函数:IndexFile也是通过MappedFile创建

    public IndexFile(final String fileName, final int hashSlotNum, final int indexNum,
        final long endPhyOffset, final long endTimestamp) throws IOException {
         
        //文件大小=indexHeader(40Byte)+HashSlotNum(500w*4Byte)+indexNum(2000w*20Byte)
        int fileTotalSize =
            IndexHeader.INDEX_HEADER_SIZE + (hashSlotNum * hashSlotSize) + (indexNum * indexSize);
        this.mappedFile = new MappedFile(fileName, fileTotalSize);
        this.fileChannel = this.mappedFile.getFileChannel();
        this.mappedByteBuffer = this.mappedFile.getMappedByteBuffer();
        this.hashSlotNum = hashSlotNum;
        this.indexNum = indexNum;
        // 共享同一个byteBuffer,但是索引位置独立
        ByteBuffer byteBuffer = this.mappedByteBuffer.slice();
        this.indexHeader = new IndexHeader(byteBuffer);
     		//初始化头文件的beginPhyOffset 和 endPhyOffset
        if (endPhyOffset > 0) {
         
            this.indexHeader.setBeginPhyOffset(endPhyOffset);
            this.indexHeader.setEndPhyOffset(endPhyOffset);
        }
    		//初始化头文件的beginTimestamp 和 endTimestamp
        if (endTimestamp > 0) {
         
            this.indexHeader.setBeginTimestamp(endTimestamp);
            this.indexHeader.setEndTimestamp(endTimestamp);
        }
    }
    

putKey

  1. 步骤

    • 计算消息key的hash
    • 根据hash计算hashsolt位置,并计算solt的实际的物理位置,hashsolt中存储的是当前构建索引的总个数,也是存储的index下标(通过this.indexHeader.getIndexCount()维护)
    • 获取solt上次存入的值,默认是0
    • 计算当前存储index的物理位置,并存入hash、phyOffset、storeTimestamp、slotValue
  2. 源码

    public boolean putKey(final String key, final long phyOffset, final long storeTimestamp) {
         
        //如果已经构建的索引index数量 < 最大的index数量,则进行插入,否则直接返回 false
        if (this.indexHe
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值