Kafka 核心源码解读
胡夕
Apache Kafka Committer,老虎证券技术总监
19216 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 44 讲
结束语 (1讲)
Kafka 核心源码解读
15
15
1.0x
00:00/00:00
登录|注册

05 | 索引(下):位移索引和时间戳索引的区别是什么?

你好,我是胡夕。今天,我们继续说索引那些事儿。
在上节课,我带你重点学习了 Kafka 源码中索引的抽象父类 AbstractIndex。我分析了 AbstractIndex 类的大体对象结构,还介绍了社区改进版的二分查找算法在 Kafka 索引上的应用。
前面说过,Kafka 索引类型有三大类:位移索引、时间戳索引和已中止事务索引。相比于最后一类索引,前两类索引的出镜率更高一些。在 Kafka 的数据路径下,你肯定看到过很多.index 和.timeindex 后缀的文件。不知你是否有过这样的疑问:“这些文件是用来做什么的呢?” 现在我可以明确告诉你:.index 文件就是 Kafka 中的位移索引文件,而.timeindex 文件则是时间戳索引文件。
那么,位移索引和时间戳索引到底是做什么用的呢?它们之间的区别是什么?今天,我就为你揭晓这些问题的答案。

位移索引

在学习 Kafka 的任何一类索引的时候,我们都要关注两个问题:
索引中的索引项是如何定义的?
如何向索引写入新的索引项?
看到这里,你可能会很疑惑:“等等,难道我们不需要关心如何查询索引吗?” 当然需要啦!上节课我们不是讲过二分查找算法在索引中的应用了吗?如果你觉得有点生疏了,那就赶快先去复习一下吧。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Kafka索引的位移索引和时间戳索引是本文的重点内容。位移索引用于定位消息的物理文件位置,通过优化相对位移的存储方式来节省空间;而时间戳索引则保存了<时间戳,相对位移值>对,占用更多磁盘空间。文章详细解释了它们的定义、写入操作以及查询逻辑,通过代码示例和解释展示了它们的实现细节。作者还分享了一个有趣的故事,强调了阅读源码的收获。最后,总结了OffsetIndex和TimeIndex的特点和区别,并提醒读者不要对索引文件做任何修改。整体而言,本文深入浅出地介绍了Kafka索引的工作原理和优化方式,以及位移索引和时间戳索引的使用方式和特点,对读者了解Kafka索引提供了有益的指导。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Kafka 核心源码解读》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(12)

  • 最新
  • 精选
  • 胡夕
    置顶
    你好,我是胡夕。我来公布上节课的“课后讨论”题答案啦~ 上节课,咱们重点了解了Kafka索引对象以及改进版的二分查找算法,课后我让你思考下改进版二分查找算法中冷区和热区的分割线设定在8192字节处的原理。鉴于这是一个开放式的问题,我说下我的理解:就像源码注释里面写的那样,8192这个数字不大不小正合适。所谓不大不小是指它并不是太小,它足以确保大多数lagging很小的follower或consumer都只在热区查询;同时它也不会太大,对于主流4KB大小的page size而言, 热区大约也就只占用2~3个页面。 okay,你是怎么考虑的呢?我们可以一起讨论下。
    2020-04-23
    6
  • Alpha 👀
    老师您好,请问一个问题,kafka记录消费者的消费offset是对消费者组,还是对单个消费者?比如一个消费者组中新加入一个消费者,分区重新分配,那新加入的消费者是从哪里开始消费?

    作者回复: 针对消费者组,或者说针对每个group id。保存的是<groupId, topicPartition, offset>三元组。新增消费者拿到要消费的分区后,去查看有无对应的三元组记录,如果没有,则根据consumer端参数auto.offset.reset值来决定从哪里开始消费

    2020-05-08
    2
    2
  • thomas
    老师,请问建立分区初始化的时候,log-segment的位移索引和时间索引文件将近有10M的数据? ---------------------------------------------------------------------------------------》 -rw-r--r-- 1 root root 10485760 Apr 25 14:23 00000000000000000000.index -rw-r--r-- 1 root root 0 Apr 25 14:23 00000000000000000000.log -rw-r--r-- 1 root root 10485756 Apr 25 14:23 00000000000000000000.timeindex

    作者回复: 里面为空,只是预分配了10MB的空间

    2020-04-25
    2
    2
  • 小虞仔
    课后作业: def lookup(targetOffset: Long): OffsetPosition = { maybeLock(lock) { val idx = mmap.duplicate val slot = smallestUpperBoundSlotFor(idx, targetOffset, IndexSearchType.KEY) if(slot == -1) OffsetPosition(baseOffset, 0) else parseEntry(idx, slot) } } //自己重写了一下二分查找,发现有现成的方法,😆

    作者回复: 嗯嗯,可以尝试写个test case,测试下自己的方法:)

    2020-05-26
    1
  • 快跑
    从消费者的角度,如果没有<groupId, topicPartition, offset>则从auto.offset.reset的offset开始读数据,这些步骤都能直接查到offset吧,那TimeIndex是在什么场景派上用场,发挥作用的?

    作者回复: 如果你要根据时间戳查询消息,TimeIndex就用上了

    2021-03-31
    2
  • z.l
    思考题,直接把lookup方法的最后一行改成 parseEntry(idx, slot+1),可以吗?

    作者回复: 好像不太严谨。如果出现等于的情况呢?

    2020-09-04
  • 对与错
    有个疑问:在leader写入消息的时候,时间戳索引项里面是 <消息集合的最后一条消息的时间戳,当前LEO的值>, 在flowwer写入消息的时候,时间戳索引项里面是 <消息集合的最后一条消息的时间戳,消息集合的最后一条消息的时间戳所对应的位移值>,为什么这么设计?

    作者回复: 逻辑是统一的,都是写入最大的时间戳以及对应的位移

    2020-08-28
  • sljoai
    胡老师,请教几个问题: 1."假设一个索引文件保存了 1000 个索引项,使用相对位移值就能节省大约 4MB 的空间,这是不是一件很划算的事情呢?!". 请问具体是怎么计算的呢?4字节 * 1000 ? 2.relativeOffset方法已经变了,我看到的是如下: private def relativeOffset(buffer: ByteBuffer, n: Int): Int = buffer.getInt(n * entrySize) 跟本文中介绍的有所不同,该怎么理解呢?

    作者回复: 1. 嗯,差不多是这么计算的 2. 逻辑变得更加简单了。每一个索引项都是<offset, position>对,那么第n项的相对位移自然就是buffer的n*entrySize字节处开始的4个字节表示的整数值

    2020-06-09
    2
  • RonnieXie
    老师,我这边对OffsetIndex 和 TimeIndex二者结合使用的理解有些模糊; 为什么需要一起使用,消费者不是根据Offset找到对于位置值开始消费就好吗?而且结合使用性能也应该降低吧?

    作者回复: 你说的没错。不过一般情况下消费者并不是直接能够定位目标offset,相反地它是通过时间戳先找到目标offset的

    2020-05-09
  • delete is create
    老师 如果用kafka实现延迟消息有没有什么好的实践 rocketmq这块原生就支持 想了解下kafka怎么做

    作者回复: 只能自己写程序实现了,Kafka没有提供这方面的机制:(

    2020-04-24
收起评论
显示
设置
留言
12
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部