04. kafka log数据清理
前言:前端时间一直在解读kafka0.10.1的客户端和服务器端的源码,主要是从整体流程上分析的源码。今天有一个同事正好有一个同事问到kafka log数据清理的问题,他说kafka是按照时间和大小对不满足条件的日志进行清理删除。
他说有这样的一个疑问,比如说通过参数把日志保留的时间参数设置为7day,日志保留的大小参数设置为100GB,有一个topic:test.kafka.log.clear在2020/01/01的时候写入了一些数据,之后就再也没有写如果数据,等过了2020/01/07日之后,会不会把所有的日志分段都删除掉呢?如果在2020/01/10再写入数据的时候是否还能正常写入?
所以,最近特意又解读了一下kafka日志清理这块儿的源码,以下通过kafka的源码解答以上两个问题。
Kafka log数据清理策略有两种方式:
Delete
Compact
可以通过参数cleanup.policy进行配置,默认采用的是Delete默认采用的是Delete策略,本篇博客我们先分析Delete策略,后面会接着分析Compact策略,这个策略也更复杂一些。
影响Delete策略的参数主要分为以下两类:
时间参数包括log.retention.ms, log.retention.minutes, log.retention.hours优先级顺序为由高到低
大小参数包括log.retention.bytes
Kafka服务端主要是通过一个叫LogManager的对象日志数据进行维护,其中会通过startup方法启动一些定时任务如下图

其中的kafka-log-retention定时任务就是负责执行delete策略日志清理,接着分析cleanupLogs方法

循环所有的Log对象,topic的每一个partition都是一个Log对象

deleteRetenionMsBreachedSegments方法是按照时间进行删除,deleteRetentionSizeBreachedSegments是按照大小进行删除


两个方法都传递了一个根据参数判断的函数给deleteOldSegments方法

第一个红框:deletableSegments判断满足删除条件的日志段的数量(以我们上面举的那个例子为例,满足删除条件的日志段的数量为1)
第二个红框:如果满足删除条件的日志段数量正好topic partition所有的日志段数量相同,此时调用roll方法生成一个空的日志段文件

通过改方法看出日志段的大小必须是大于0的,也就是说空的日志段是不可以删除的,就算超过了7天的有效期,也不能删除
自此,我们解答了上面的两个疑问,第一会不会把所有的日志都删除了,回答不会,最少会保留一个空的日志段文件.第二个是否还能正常写入数据,回答因为有至少一个空日志段文件按,所以能正常写入数据