Kafka 作为一个高吞吐的消息中间件和传统的消息中间件一个很大的不同点就在于它的消息实际上是以日志的方式默认保存在/tmp/kafka-logs文件夹中的。
Kafka的持久化策略更像Redis——数据都在内存中,定期刷写到硬盘上持久化存储,以保证重启的时候数据不丢。刷写策略由log.flush.*这些参数控制。
Kafka每个Topic可以存储于多个Partition,每个Partition在Kafka的log目录下表现为 topicname-id 这样的文件夹,如mytopic-0。Kafka队列中的内容会按照日志的形式持久化到硬盘上,每个日志文件称为”片段”(Segment)。
Kafka清理队列中过期消息的方式实际上就是删除过期的Segment,这种表现形式十分类似于日志滚动,因此控制Kafka队列中消息的保存时间的方式实际上就是日志文件定期分段,然后定期清理掉过期的段文件。
一、分段文件解析
每个Segment包含一个日志文件(.log后缀)和两个索引文件(.index和 .timeindex后缀)。
1. 日志文件(log)
可以通过kafka-run-class.sh kafka.tools.DumpLogSegments --files 00000000000000000000.log --print-data-log命令查看log文件中存放的是具体的每条消息,其每条消息包含的内容如下。
- baseOffset:当前batch中第一条消息的位移。
- lastOffset:最新消息的位移相对于第一条消息的唯一增量。
- count:当前batch有的数据数量,kafka在进行消息遍历的时候,可以通过该字段快速的跳跃到下一个batch进行数据读取。
- partitionLeaderEpoch:记录了当前消息所在分区的 leader 的服务器版本,主要用于进行一些数据版本的校验和转换工作。
- crc:当前整个batch的数据crc校验码,主要用于对数据进行差错校验的。
- compresscode:数据压缩格式,主要有GZIP、LZ4、Snappy三种。
- Sequence、producerId、producerEpoch:这三个参数主要是为了实现事务和幂等性而使用的,其中producerId和producerEpoch用于确定当前 producer 是否合法,而起始序列号则主要用于进行消息的幂等校验。
- isTransactional:是否开启事务。
- magic:Kafka服务程序协议版本号。
- CreateTime:数据创建的时间戳。
- payload:实际存储的数据。
2. 偏移量索引文件
使用kafka-run-class.sh kafka.tools.DumpLogSegments --files 00000000000000000000.index --print-data-log命令查看文件内容。
- offset:这条数据在这个 Segment 文件中的位置,是这个文件的第几条。
- position : 这条数据在 Segment 文件中的物理偏移量。
3. 时间戳索引文件
查看文件的命令同偏移量索引文件查看命令。
- timestamp:该日志段目前为止最大时间戳。
- offset:记录的是插入新的索引条目时,当前消息的偏移量。
二、日志策略
1. 分段策略属性
属性名 | 含义 | 默认值 |
log.roll.{hours,ms} | 日志滚动的周期时间,到达指定周期时间时,强制生成一个新的segment | 168(7天) |
log.segment.bytes | 每个segment的最大容量。到达指定容量时,将强制生成一个新的segment | 1G(-1为不限制) |
log.retention.check.interval.ms | 日志片段文件检查的周期时间 | 60000 |
2. 日志刷新策略
属性名 | 含义 | 默认值 |
log.flush.interval.messages | 消息达到多少条时将数据写入到日志文件 | 10000 |
log.flush.interval.ms | 当达到该时间时,强制执行一次flush | null |
log.flush.scheduler.interval.ms | 周期性检查,是否需要将信息flush | 9223372036854775807 |
3. 日志保存清理策略
属性名 | 含义 | 默认值 |
log.cleanup.polict | 日志清理保存的策略只有delete和compact两种 | delete |
log.retention.hours | 日志保存的时间,可以选择hours,minutes和ms | 168(7天) |
log.retention.bytes | 删除前日志文件允许保存的最大值 | -1 |
log.segment.delete.delay.ms | 日志文件被真正删除前的保留时间 | 60000 |
log.cleanup.interval.mins | 每隔一段时间多久调用一次清理的步骤 | 10 |
log.retention.check.interval.ms | 周期性检查是否有日志符合删除的条件(新版本使用) | 300000 |
- 日志的真正清除时间。当删除的条件满足以后,日志将被“删除”,但是这里的删除其实只是将该日志进行了“delete”标注,文件只是无法被索引到了而已。但是文件本身,仍然是存在的,只有当过了log.segment.delete.delay.ms 这个时间以后,文件才会被真正的从文件系统中删除。
三、总结
本文讲解了Apache Kafka消息日志的组成结构以及消息日志的保存和清理的参数设置,大家可以根据文中提供的文件查看命令去实际查看自己测试集群上的某个topic下的文件,在Kafka中设置消息日志的各种参数,体验不同的效果,找到最适合的配置。