使用OffsetIndex
OffsetIndex被用来快速定位消息所在的物理文件位置,那么必然需定义一个方法执行对应的查询逻辑。这个方法就是lookup。
该方法返回的,是不大于给定位移值targetOffset的最大位移值,以及对应的物理文件位置。你大致可以把这个方法,理解为位移值的FLOOR函数。
2 TimeIndex - 时间戳索引
2.1 定义
用于根据时间戳快速查找特定消息的位移值。
TimeIndex保存<时间戳,相对位移值>
对:
- 时间戳需长整型存储
- 相对偏移值使用Integer存储
因此,TimeIndex单个索引项需要占12字节。
存储同数量索引项,TimeIndex比OffsetIndex占更多磁盘空间。
2.2 写索引
- maybeAppend
- 向TimeIndex写索引的主体逻辑,是向mmap分别写入时间戳和相对偏移值。
除校验偏移值的单调增加性之外,TimeIndex还会确保顺序写入的时间戳也单调增加。
不单调增加会咋样?
向TimeIndex索引文件中写入一个过期时间戳和位移,就会导致消费端程序混乱。因为,当消费者端程序根据时间戳信息去过滤待读取消息时,它读到了这个过期时间戳并拿到错误位移值,于是返回错误数据。
3 总结及 FAQ
虽然OffsetIndex和TimeIndex是不同类型索引,但Kafka内部把二者结合使用。通常先使用TimeIndex寻找满足时间戳要求的消息位移值,然后再利用OffsetIndex定位该位移值所在的物理文件位置。因此,它们其实是协作关系。
二者的 broker 端参数都是log.index.size.max.bytes
为什么需要一起使用,消费者不是根据Offset找到对于位置值开始消费就好吗?而且结合使用性能也应该降低吧?
没错。不过一般情况下消费者并不是直接能够定位目标offset,相反地它是通过时间戳先找到目标offset。
不要对索引文件做任何修改!擅自重命名索引文件可能导致Broker崩溃无法启动的场景。虽然Kafka能重建索引,但随意删除索引文件很危险!
建立分区初始化的时候,log-segment的位移索引和时间索引文件将近有10M的数据?
里面为空,只是预分配了10MB的空间
kafka记录消费者的消费offset是对消费者组,还是对单个消费者?比如一个消费者组中新加入一个消费者,分区重新分配,那新加入的消费者是从哪里开始消费?
针对消费者组,或者说针对每个group id。保存的是<groupId, topicPartition, offset>三元组。新增消费者拿到要消费的分区后,去查看有无对应的三元组记录,如果没有,则根据consumer端参数auto.offset.reset值来决定从哪里开始消费
Kafka没有提供延时消息机制,只能自己实现的哈。