今天正常下班,哈哈哈哈哈,来继续看日志存储😎~
偏移量索引
至于为什么说Integer.MAX_VALUE
是影响日志分段切分的因素之一,就要好好理解一下偏移量索引了,一起看看吧👀
不熟悉Java的小伙伴突然看Integer.MAX_VALUE
可能会有点懵,Integer.MAX_VALUE
是java.lang
包中的Integer类中的一个常量,它指定在Java中存储任何整数变量的最大可能值,实际值为2^31-1 = 2147483647
,可以通过Java的官方文档查找查看: https://docs.oracle.com/javase/8/docs/api/index.html
偏移量索引文件用来建立消息偏移量到物理地址之间的映射关系,方便快速定位消息所在的物理文件位置。
偏移量索引项由两个部分组成:
- relativeOffset(相对偏移量),表示消息相对于baseOffset的偏移量(
relativeOffset = offset - baseOffset
),占4个字节,当前索引文件的文件名就是baseOffset的值; - position(物理地址),表示消息在日志分段文件中对应的物理位置占,4个字节。
消息的偏移量(绝对偏移量)占用8个字节,索引项中不使用绝对偏移量,采用相对偏移量是因为这样可以减小索引文件占用的空间。比如日志分段00000000000000000032.log
,offset为35的消息在索引文件中的relativeOffset的值为3。
所以当追加的消息的偏移量与当前日志分段的偏移量差值大于Integer.MAX_VALUE
时,relativeOffset无法用4个字节表示,日志分段文件及对应的索引文件就会进行切分,要说为什么是4个字节,就需要看Java的语言规范了: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
另外,Kafka中索引文件大小必须是索引项大小的整数倍,就偏移量索引文件来说,必须为8的倍数,如果broker端参数log.index.size.max.bytes
配置为67,Kafka会在内部将其转化为64。
时间戳索引
时间戳索引文件根据指定的时间戳来查找对应的偏移量信息,与偏移量索引文件相似,时间戳索引文件大小必须是索引项大小(12B)的整数倍。
时间戳索引项由两个部分组成:
- timestamp: 当前日志分段最大的时间戳,占8个字节,时间戳索引文件中会包含若干时间索引项,每个追加的时间戳索引项中的timestamp必须大于之前追加的timestamp,否则不予追加;
- relativeOffset: 时间戳所对应的消息的相对偏移量,占4个字节。
写入一定量消息时,会在偏移量索引文件和时间戳索引文件中分别增加一个偏移量索引项和时间戳索引项,两个操作同时进行,但并不意味着偏移量索引项中的relativeOffset和时间戳索引项中的relativeOffset是同一个值。
参考
1、《深入理解Kafka: 核心设计与实践原理》
2、How Kafka’s Storage Internals Work