Kafka的日志存储设计

Kafka中的日志存储并不是直接存储的一条条的消息,而是将多条消息和一些必要的元数据进行打包封装在一起形成一个record写入日志。形成我们所讲的消息集合或者消息batch.

图片

而在record中,一条消息会被分配到一个唯一的位移标识,并伴随着一个消息的时间戳信息。在之前讲过,V2版本的消息会在一个record中携带一个完整的时间戳和位移信息,而每条消息只是携带着增量信息。

Kafka在更上层,是以分区为单位的,每个分区都有自己的日志,称为partition log,而为了方便管理,也方便查询,又进一步的细分为了日志段文件 log segment file,日志段索引文件。

基本构成有

.log文件 .index文件 .timeindex文件

分别对应着日志存储文件,保存着真实的kafka记录,文件名是这个文件记录的第一条record,故第一个分区日志文件往往是全是0。而且为了方便管理,日志文件是具有大小上线的,由broker端参数 log.segment.bytes控制,默认1GB,达到后会自动创建新的。

索引文件,分别包含.index和.timeindex文件,为了从位移来定位消息和从时间戳定位消息。

不过都是稀疏索引,也就是每写入多个record,才会增加一条索引。这个写入间隔由log.index.interval.bytes来控制。

内部结构为 图片

每个索引项由8个字节构成,而且上面表示,并非直接保存索引的全量位置,而只保存差值。从而减少磁盘空间占用。

而且在内部查询,实际上使用的是二分查找法,比如broker要查找位移为7000的消息,那么会在索引文件上查找到小于7000的最大索引项。比如是6600,根据这个索引项对应的物理位移,开始往后查找。找到7000所在的物理索引位置。

而时间戳索引的格式为 图片

保存的是全量时间戳。而且查找方式和索引文件一致,进行二分查找。

对于日志的留存,也就是为了维持日志的占用空间大小,会对一些符合条件的日志进行清理。

留存策略主要有两种,

首先是基于时间的留存策略,会默认清理前7天的日志段,设置log.rentention.{hours,minutes,ms}

然后是基于大小的留存,控制log的总大小,通过log.retention.bytes参数大小,默认为-1,不会对log进行大小方面的限制。

日志的压实

则是对于很多topic的数据,如果key相同,那么往往只需要最新一条的消息。而Kafka的压实,就是一段时间后,将多个key的消息改为只保留最新一条key的消息。

对于整个执行流程,分为了log tail和log head, tail中包含已经压实过得了,head中的则还没有。Kafka会有一个组件叫做Cleaner,会负责compaction的操作,会对head进行清理,而head中还分为可清理和不可清理的。不可清理的日志段包括当前日志段。而对可清理日志段清理的过程,则是构建一个哈希表,进行记录相同key的消息,从而只保留最新一条的消息。

在consumer group中保存组内消费位移的kafka 内部topic就活用了消息压实操作

压实相关参数有

Log.cleanup.policy 可选 log delete和compact分别是删除和压实

Log.cleaner.enable 是否启用log Cleaner

Log.cleaner.min.compaction.lag.ms 可清理的时间,就是在比当前时间小一定时间段的日志不被清理。

发表评论

邮箱地址不会被公开。 必填项已用*标注