kafka 日志清除
日志删除
Kafka 日志管理器中会有一个专门的日志删除任务来周期性检测和删除不符合保留条件的日志分段文件,这个周期可以通过 broker 端参数log.retention.check.interval.ms 来配置,默认值为 300,000,即5分钟。当前日志分段的保留策略有3种:基于时间的保留策略、基于日志大小的保留策略以及基于日志起始偏移量的保留策略。
基于时间

kafka segment
查找过期的日志分段文件,并不是简单地根据日志分段的最近修改时间lastModifiedTime 来计算,而是根据日志分段中最大的时间戳largestTimeStamp 来计算。因为日志分段的 lastModifiedTime 可以被有意或者无意的修改,比如执行了 touch 操作,或者分区副本进行了重新分配,lastModifiedTime 并不能真实地反映出日志分段在磁盘的保留时间。要获取日志分段中的最大时间戳 largestTimeStamp 的值,首先要查询该日志分段所对应的时间戳索引文件,查找时间戳索引文件中最后一条索引项,若最后一条索引项的时间戳字段值大于0,则取其值,否则才设置为最近修改时间 lastModifiedTime。
root@kafka-1:/opt/kafka/data/logs/v2xRTData-0# kafka-dump-log --files /opt/kafka/data/logs/v2xRTData-0/00000000000005357795.timeindex
...
timestamp: 1669782936152 offset: 5366863
timestamp: 1669782937050 offset: 5366872
timestamp: 1669782937954 offset: 5366881
timestamp: 1669782938850 offset: 5366890
timestamp: 1669782939752 offset: 5366899
timestamp: 1669782940648 offset: 5366908
若待删除的日志分段(阴影部分)的总数等于该日志文件中所有的日志分段的数量,那么说明所有的日志分段都已过期,但是该日志文件中还要有一个日志分段来用于接收消息的写入,即必须要保证有一个活跃的日志分段 activeSegment,在此种情况下,会先切分出一个新的日志分段作为 activeSegment,然后再执行删除操作。
删除日志分段时,首先会从日志文件对象中所维护日志分段的跳跃表中移除待删除的日志分段,以保证没有线程对这些日志分段进行读取操作。然后将日志分段文件添加上 .deleted 的后缀,当然也包括日志分段对应的索引文件。最后交由一个以 delete-file 命名的延迟任务来删除这些 .deleted 为后缀的文件,这个任务的延迟执行时间可以通过 file.delete.delay.ms参数来设置,默认值为 60000,即1分钟。
基于日志大小

日志删除任务会检查当前日志的大小是否超过设定的阈值 retentionSize 来寻找可删除的日志分段的文件集合 deletableSegments,参考下图所示。retentionSize 可以通过 broker 端参数 log.retention.bytes 来配置,默认值为-1,表示无穷大。注意 log.retention.bytes 配置的是日志文件的总大小,而不是单个的日志分段的大小,一个日志文件包含多个日志分段。
基于日志大小的保留策略与基于时间的保留策略类似,其首先计算日志文件的总大小size 和 retentionSize 的差值diff,即计算需要删除的日志总大小,然后从日志文件中的第一个日志分段开始进行查找可删除的日志分段的文件集合 deletableSegments 。查找出 deletableSegments 之后就执行删除操作,这个删除操作和基于时间的保留策略的删除操作相同,这里不再赘述。
基于日志起始偏移量

一般情况下日志文件的起始偏移量 logStartOffset 等于第一个日志分段的baseOffset,但是这并不是绝对的,logStartOffset 的值可以通过DeleteRecordsRequest 请求、日志的清理和截断等操作修改。
基于日志起始偏移量的删除策略的判断依据是某日志分段的下一个日志分段的起始偏移量 baseOffset 是否小于等于 logStartOffset,若是则可以删除此日志分段。参考上图,假设 logStartOffset 等于25,日志分段1的起始偏移量为0,日志分段2的起始偏移量为11,日志分段3的起始偏移为23,那么我们通过如下动作收集可删除的日志分段的文件集合deletableSegments:
-
从头开始遍历每个日志分段,日志分段1的下一个日志分段的起始偏移量为11,小于
logStartOffset的大小,将日志分段1加入到deletableSegments中; -
日志分段2的下一个日志偏移量的起始偏移量为23,也小于
logStartOffset的大小,将日志分段2页加入到deletableSegments中;
日志分段3的下一个日志偏移量在 logStartOffset 的右侧,故从日志分段3开始的所有日志分段都不会被加入到 deletableSegments中。