RocketMQ 之 IndexFile

·  阅读 673

[toc]

概述

CommitLog 作为消息存储的载体;ConsumeQueue 面向消费端,被设计为 CommitLog 的消息索引;IndexFile 则提供了一种可以通过 key 或时间区间来查询消息的方法。 下面,就来介绍 IndexFile

IndexFile 设计介绍

IndexFile 文件的命名为:当前文件创建时的时间,精确到毫秒。例如 20210626134145150

IndexFile 结构如下

image.png

IndexHead

  • beginTimestamp

文件中消息的最小存储时间

  • endTimestamp

消息的最大存储时间

  • beginPhyoffset

消息的最小偏移量

  • endphyoffset

消息的最大物理偏移量

  • hashSlotCount

已用 hash 槽个数

  • indexCount

已用 index 个数

IndexHead 的结构,我们可以看出,主要是一些总指标,这些指标,都是为了它方便进行 增删改查

Hash 槽 hash 槽,每个子元素,有 4 个字节。 槽上存储的是 key 的 hash 值。 这里的 key 指:topic + # + 消息的 key 或 topic + # + uniqKeykey 由生产者发送消息时填写,多个用 空格 隔开。 槽上存储的是:最新的 item 在 Index 上的位置

Index Item

  • hashcode

keyhashcode

  • pyhoffset

commitlog 的物理偏移量

  • timeDiff

timeDiff = commitLog 写入时间 - IndexFile 第一条消息写入时间

  • preIndexNo

preIndexNo 把 hash 冲突的 item 组成链表。hash 槽上的记录的元素的位置,永远是最新加入的 item 位置。

IndexFile 消息写入

写入 key1 后, IndexFile 变成了这样子

image.png

写入 key2 后, hash 出现冲突,RocketMQ 会利用 Index itempreIndexNo 解决冲突 image.png

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

image.png

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

分类:
后端
标签: