[toc]
概述
CommitLog 作为消息存储的载体;ConsumeQueue 面向消费端,被设计为 CommitLog 的消息索引;IndexFile 则提供了一种可以通过 key 或时间区间来查询消息的方法。
下面,就来介绍 IndexFile。
IndexFile 设计介绍
IndexFile 文件的命名为:当前文件创建时的时间,精确到毫秒。例如 20210626134145150
IndexFile 结构如下

IndexHead
beginTimestamp
文件中消息的最小存储时间
endTimestamp
消息的最大存储时间
beginPhyoffset
消息的最小偏移量
endphyoffset
消息的最大物理偏移量
hashSlotCount
已用 hash 槽个数
indexCount
已用 index 个数
从 IndexHead 的结构,我们可以看出,主要是一些总指标,这些指标,都是为了它方便进行 增删改查
Hash 槽
hash 槽,每个子元素,有 4 个字节。
槽上存储的是 key 的 hash 值。
这里的 key 指:topic + # + 消息的 key 或 topic + # + uniqKey。key 由生产者发送消息时填写,多个用 空格 隔开。
槽上存储的是:最新的 item 在 Index 上的位置
Index Item
hashcode
key 的 hashcode
pyhoffset
commitlog 的物理偏移量
timeDiff
timeDiff = commitLog 写入时间 – IndexFile 第一条消息写入时间
preIndexNo
preIndexNo 把 hash 冲突的 item 组成链表。hash 槽上的记录的元素的位置,永远是最新加入的 item 位置。
IndexFile 消息写入
写入 key1 后, IndexFile 变成了这样子

写入 key2 后, hash 出现冲突,RocketMQ 会利用 Index item 的 preIndexNo 解决冲突

写入 key3, hash 未出现冲突,正常写入

IndexFile 查找消息
知道了 IndexFile 如何处理 hash 冲突了,那根据 key 查询就很好理解了。
按照 key 进行查询的时候,根据 hash 槽上的 index item 位置 定位到 最新的 index item, 然后根据 preIndexNo 往前查找,直到 preIndexNo = 0 停止。
因为,index item 存储着 commitlog 的偏移量,因为可以找到具体的消息
IndexFile 落盘
IndexFile 没有专门的线程处理刷盘。
在 RocketMQ 当中,CommitLog, ConsumeQueue, IndexFile 都是通过 mmap()(后续讲解) 创建出来的文件。在内存操作,相当于操作磁盘上的文件。但是刷盘的动作,依赖操作系统。
以下为个人观点
IndexFile 只是用于对 CommitLog 进行索引(方便运维),在 RocketMQ 的存储主线中,并非那么重要,所以不专门提供刷盘线程,刷盘动作直接依赖操作系统
为什么说 IndexFile 可能不是那么重要呢?因为 ReputMessageService 在转发时,可通过参数 messageIndexEnable 关闭转发至 IndexFile



















![[桜井宁宁]COS和泉纱雾超可爱写真福利集-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/4d3cf227a85d7e79f5d6b4efb6bde3e8.jpg)

![[桜井宁宁] 爆乳奶牛少女cos写真-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/d40483e126fcf567894e89c65eaca655.jpg)