9.rocketmq源代码学习---索引文件结构

索引文件主要是解决根据key查找消息列表的问题,那么rocketmq是怎么设计的呢?

IndexFile索引结构如下:

在这里插入图片描述

主要包含三部分:

A.第一部分: IndexHeader

IndexHeader索引头共占用40个字节(8byte(long类型)*4个+4byte(int类型)*2个),就是以下6个值:

beginTimestamp = new AtomicLong(0);  //第一个索引消息的storeTimestamp
endTimestamp = new AtomicLong(0);  //最后一个索引消息的storeTimestamp
beginPhyOffset = new AtomicLong(0);  //第一个索引消息的commitLogOffset
endPhyOffset = new AtomicLong(0);  //最后一个索引消息的commitLogOffset
hashSlotCount = new AtomicInteger(0);  // 目前索引占用的槽数量
indexCount = new AtomicInteger(1);  //当前已写入的索引数量,用于判断总数必须 < 500,0000

B、第二部分:HashSlot

一个索引文件可以保存500w个索引,HashSlot设置了500w个卡槽,每个卡槽代表一类hash值的最后一个索引的计数,所以HashSlot长度共:500w*4byte;

rocket索引是使用链表的形式来存储,类似于hashmap的结构,hash值相同的key用链结构连接起来。

C、第三部分:索引内容

每一个索引结构如下:
在这里插入图片描述

keyhash: key的hash值
phyOffset:消息的commitLogOffset
timeOffset:消息的storeTimeStamp和IndexHeader的startTimestamp的时间差
slotValue:链表迭代的上一个索引位置

每个索引需要20byte,总共即是:20byte*500w

这样讲还是比较抽象,我们来举一个例子:
IndexHeader就不说了,理解起来比较简单。

举例说明:
①新发送一个消息,消息key=abc,假设计算的hash值为:96354
那么先找到卡槽96354位置的值,由于是第一个索引,所以值为0
由于是第一个索引,所以将数据放入到索引1的位置,
并修改卡槽96354的值为 1 ,表示是第一个索引
如图:
在这里插入图片描述

②新发送一个消息,消息key=abd,假设计算的hash值为:96355
那么先找到卡槽96355位置的值,发现值为0(从没有存储过hash=96355的索引)
由于之前已经有了一个索引,所以将数据放入到索引2的位置,
并修改卡槽96355的值为 2 ,表示目前hash=96355的key对应的索引位置是第2个
如图:
在这里插入图片描述

③新发送一个消息,消息key=xxx,假设计算的hash值为:96354+500w
那么对应的卡槽位置为:(96354+500w)%500w=96354
那么先找到卡槽96354位置的值,发现值为1(表示当前已经有一个索引数据,并且在第一个索引位置)
当前是第三个索引,将数据放入到第三个索引位置,并且索引3数据中的卡槽值设置为上一个索引的位置,即:卡槽96354的值1。
并修改卡槽96354的值为3 ,表示目前hash=96354的key对应的索引位置是第3个
如图:
在这里插入图片描述

④同理,假如再发送一个消息,hash值同样为 96354
在这里插入图片描述

查询举例:
假设现在根据key=abc查询,计算出key的hash值=96354
那么查询的步骤如下:
1、根据key hash得知hash = 96354,计算卡槽位置,得知 96354 % 500,0000 = 96354
2、读取卡槽96354处的值,得到结果为4
3、读取索引4位置的消息所在phyOffset,则可以获取到消息内容,同时可获取到索引4处(上一卡槽值) 为 3
4、然后读取第三个索引的值,获取到索引3处(上一卡槽值)为1
5、以此类推,读取到索引1处 的key

最终获取到索引1、索引3、索引4
再根据commitLogOffset获取到消息内容,同时获取到消息key,比较发现key不同,则忽略

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值