# 文件结构
前面说过kafka的有序是分区的有序性,一个分区时一个log文件,一个log文件划分为多个日志分段(logsegment)。其中log在物理存储上只以文件夹的形式存储,每个logsegmen对应磁盘上的一个日志文件和2个索引文件。
消息压缩
在kafka中,kafka将多条消息一起压缩。发送到broker之后也是保持压缩状态存储,消费者端从broker获取到的也是压缩的消息,消费者在处理这些消息的时候才会解压消息。
多个消息压缩到一起发送,这个压缩体叫做外层消息,里面有个value保存的则是多个压缩的消息,叫做内层消息。内层消息内部是多个消息的压缩,内部自己维持一个offset,从0开始,同时外层消息也有个offset,这个offset是内层消息最后一个offset的实际位移。
外层消息也有个timestamp。
- 当这个timestamp类型是createTime,那么设置的是内层消息的最大时间戳。
- 当这个类型是LogAppendTime,那么设置的是kafka服务器当前时间戳。
内层消息里面有个时间戳timestamp。
- 当这个外层timestamp类型是createTime,那么内层消息的时间戳设置的是生产者创建消息时的时间戳。
- 当这个外层timestamp类型是createTime,那么内层消息的时间戳会被忽略。
*变长长度
kafka引入Varints变长整形,Varints是使用一个或者多个字节来序列化整数的方法,数值越小,占用字节数越小,Varints每个字节除了最后一个字节外最高位都是1。最后一个字节最高位是0,用于区分是否表示一个整数,除了最高位,其余的位表示数据存储。由于是变长字段,因此存储消息时很灵活。日志索引
前面说了每个日志分段文件对应2个索引文件,但是不保证每个消息都可以在索引文件里面找到索引项的。这个索引文件时每当消息,写入一定量(log.index.interval.bytes默认4kb),偏移量索引文件和时间索引文件会分别增加一个索引项。索引文件都是按顺序递增的,因此我们可以使用二分查找来。
日志文件也会分隔,满足以下条件就会分隔
- 日志文件大小超过 log.segment.bytes,分隔,默认1GB。
- 当前日志分段中最大时间戳和当前系统时间戳差值大于log.roll.ms或者log.roll.hours,第一个优先级最高,但是默认第二个,也就是一周。
- 2个索引文件大小超过log.index.size.max默认10MB时。
- 追加消息偏移量和当前日志最大的偏移量的差值大于Integer.MAX_VALUE。
对于非活跃日志分段,对应的索引文件是只读,对于活跃日志分段,对应的日志分段是可读写,在索引文件切分的时候,则变成只读,同时创建可读写的新的索引文件。其文件会预分配log.index.size.max.bytes的大小空间.只有当索引文件裁剪时才会将文件剪裁到实际大小。
#