KAFKA日志存储、日志清理
1. 日志存储
kafka的消息是以topic为单位进行归类的,各个topic之间互相独立,互不影响。每个主题拥有分为一个或者多个partition(分区),每个 partition 对应于一个 log 文 件,该 log 文件中存储的就是 producer 生产的数据。Producer 生产的数据会被不断追加到该 log 文件末端,且每条数据都有自己的 offset
上图中,topic主题共有三个分区,每个分区存在一个以topic-partition命名的目录,目录下的文件结构如下表
文件类别 |
作用 |
.index |
消息的物理地址的偏移量索引文件 |
.timeindex |
映射时间戳和相对offset |
.log |
日志文件(消息存储文件) |
.snapshot |
对幂等型或者事务性producer所生成的快照文件 |
leader-epoch-checkpoint |
保存了每一任leader开始写入消息时的offset,会定时更新 |
kafk日志追加是顺序写入的,.index 和 .log 文件以当前 segment 的第一条消息的偏移量命名,偏移量是一个64位的长整型数值,固定是20位数字,长度未达到,用0进行填补。
1.1. index文件
index文件和timeindex文件是一一对应的,index中的索引条数,由参数log.segment.bytes和log.index.interval.bytes共同决定。
kafka的index采用的是稀疏索引,索引文件大小默认为10M,由参数log.index.size.max.bytes控制,Kafka在创建索引文件的时候会为其预分配log.index.size.max.bytes大小的空间,注意这一点与日志分段文件不同,只有当索引文件进行切分的时候,Kafka才会把该索引文件裁剪到实际的数据大小。也就是说,与当前活跃的日志分段对应的索引文件的大小固定为log.index.size.max.bytes,而其余日志分段对应的索引文件的大小为实际的占用空间。
配置项 |
作用 |
默认值 |
log.index.size.max.bytes |
index文件最大大小 |
|
log.segment.bytes |
分段日志文件大小 |
默认1G |
log.index.interval.bytes |
索引间隔 |
默认4K |
查看.index文件命令:
kafka-dump-log.sh --files ./00000000000000000000.index
index文件中的内容如下:
offset与position都是维护的对应片段文件的offset以及position,这里采取的是稀疏存储也就是选取一些消息的offset以及position进行存储,因为如果把对应片段的所有消息的索引都存储,那么必然会占用大量的内存。
如果要查找offset为4031802的消息,首先会通过二分找到对应的segment,然后去对应的index文件通过二分找到不大于4031802的最大索引项,也就是[offset: 4031789 position: 16906],之后进行顺序扫描。即先通过二分法在.index文件找到offset为4031789 的那条,再从log文件中的物理偏移量为12605的位置开始顺序查找偏移量为4031802的消息
1.2. timeindex文件
查看.timeindex文件命令
kafka-dump-log.sh --files ./00000000000000000000.timeindex
timeindex文件中的内容如下
如果要查找timstamp为1663899378988开始的消息,首先将时间戳和每个log文件中最大的时间戳largestTimeStamp进行逐一对比,直到找到不小于1663899378988所对应的segment。找到log文件后,使用二分法定位,找到不大于1663899378988的最大索引项,也就是[timestamp: 1663899378338 offset: 4031789],拿着偏移量是4031789的offset值去偏移量索引文件找到不大于4031789的最大索引项,也就是[offset: 4031789 position: 16906],之后从偏移量为16906的位置开始顺序查找,找到timestamp不小于1663899378988的消息。
1.3. log文件
查看log文件命令:
bin/kafka-run-class.sh kafka.tools.DumpLogSegments --files ./00000000000000000000.log --print-data-log
log文件内容如下:
|
含义 |
offset |
表示该分区的记录偏移量,指的是第几条记录 |
position |
表示该记录在当前片段文件的文件偏移量 |
CreateTime |
记录创建的时间 |
isValid |
记录是否有效 |
keysize |
表示key的长度 |
valuesize |
表示value的长度 |
magic |
表示本次发布kafka服务程序协议的版本号 |
compresscodec |
压缩工具 |
sequence |
消息的序列号 |
payload |
表示具体的消息 |
1.4. leader-epoch-checpoint文件
leader-epoch-checkpoint文件的内容如下:
0 #版本号 7 #下面的记录数 1 0 #[epoch offset] 4 581611 #[epoch offset] 5 581726 #[epoch offset] 6 581975 #[epoch offset] 7 1616781 #[epoch offset] 8 1616782 #[epoch offset] 10 4031620 #[epoch offset]
说明:
epoch表示leader的版本号,从0开始,leader每变更一次epoch就会加1
offset表示对应该epoch版本的leader写入第一条消息的offset
2.日志清理
kafka提供了两种清理策略:日志删除和日志压缩,可以通过参数log.cleaner.policy进行配置,参数可选[compact,delete],默认值是delete
2.1.日志删除[delete]
按照一定的策略,将不满足条件的日志分段文件进行删除。日志删除的配置如下:
配置 |
默认值 |
说明 |
log.retension.check.interval.ms |
300000(毫秒) |
日志清理器检查日志是否符合删除条件的频率(毫秒) |
log.retension.bytes |
-1 |
保留日志文件的最大值 |
log.segment.bytes |
1073741824 |
单个日志文件的最大大小 |
log.retention.hours |
168(小时) |
日志保留时间(小时) |
log.retention.minutes |
|
日志保留时间(分组) |
log.retention.ms |
|
日志保留时间(毫秒) |
file.delete.delay.ms |
60000(毫秒) |
从磁盘中删除的延迟时间(毫秒) |
若待删除的日志分段的总数等于该日志文件中所有的日志分段的数量,那么说明所有的日志分段都已过期,但是该日志文件中还要有一个日志分段来用于接收消息的写入,即必须要保证有一个活跃的日志分段文件activeSegment,在此种情况下,会先切分出一个新的日志分段作为activeSegment,然后再执行删除操作。
2.2.日志压缩[compact]
属于细粒度的压缩,以key为粒度的清理。针对每个消息的key进行整合,对于有相同key的不同的value值,只保留最后一个版本。也支持对单个的topic进行配置清理策略,参数cleaner.policy,压缩策略通过compression.type进行指定,可选值为['none', 'gzip', 'snappy', 'lz4', 'zstd']。
2.2.1效果
根据key只保留最新的value,如果value为null,该key一段时间后会被清理
2.2.2选择合适的文件
根据日志污浊率限定清理范围
log.cleaner.min.cleanable.ratio(默认值为0.5)
dirtyRatio=dirtyBytes/(cleanBytes + dirtyBytes)
日志污浊率=dirty部分的日志占用大小/(clean部分的日志占用大小+dirty部分日志占用大小)
2.2.3流程
- 压缩过程中将需要保留的消息拷贝到一个.clean为后缀的临时文件中(xxxx.log.clean)
- 压缩后将.clean文件修改为.swap文件(xxxx.log.clean->xxxx.log.swap)
- 删除原有log文件,将.swap后缀删除(xxxx.log.swap->xxxx.log)
这里只以log为例,压缩方式是针对整个segment(.index,.timeindex,.log)
2.2.4重新分组
因为压缩后的各个segment都会变小,需要重新分组来写log和index
将多个小的文件进行合并(log大小之和为1G,index文件之和为10m(默认情况))
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了