目前,与log4j动态修改日志级别留存方式相关的策略类型主要有两种:delete和compact這两种留存方式的机制完全不同。本文主要讨论针对delete类型的留存策略用户可以通过设置broker端参数log.cleanup.policy来指定集群上所有topic默认的策略类型。另外吔可以通过topic级别参数cleanup.policy来为某些topic设置不同于默认值的策略类型当前log.cleanup.policy参数的默认值是[delete,compact],这是一个list类型的参数表示集群上所有topic会同时开启delete和compact兩种留存策略——这是0.10.1.0新引入的功能,在0.10.1.0之前该参数只能两选一,不能同时兼顾但在实际使用中很多用户都抱怨compact类型的topic存在过期key消息未删除的情况,故社区修改了该参数配置允许一个topic同时开启两种留存策略。
再次强调下 本文只讨论delete类型的留存策略。
二、留存机制及其工作原理
在开始详细介绍各种留存机制之前先简要说下Kafka是如何处理log4j动态修改日志级别留存的。每个Kafka broker启动时都会在后台开启一个定时任务,定期地去检查并执行所有topiclog4j动态修改日志级别留存这个定时任务触发的时间周期由broker端参数log.retention.check.interval.ms控制,默认是5分钟即每台broker每5分钟都会尝試去检查一下是否有可以删除的log4j动态修改日志级别。因此如果你要缩短这个间隔只需要调小log.retention.check.interval.ms即可。
鉴于log4j动态修改日志级别留存和log4j动态修妀日志级别删除实际上是一个问题的两个方面因而我们下面讨论的是关于Kafka根据什么规则来删除log4j动态修改日志级别。但有一点要强调一下待删除的标的是log4j动态修改日志级别段,即LogSegment也就是以.log结尾的一个个文件,而非整个文件夹另外还有一点也很重要,当前log4j动态修改日志級别段(active logsegment)是永远不会被删除的不管用户配置了哪种留存机制。
当前留存机制共有3种:
前两种策略相信大家已经耳熟能详而第三种策畧由于新加入的时间不长,目前网上对其的介绍并不多我们一个一个来看。
一旦用户设置了阈值那么Kafka就会在定时任务中尝试比较当前log4j動态修改日志级别量总大小是否超过阈值至少一个log4j动态修改日志级别段的大小。这里所说的总大小是指所有log4j动态修改日志级别段文件的大尛不包括索引文件的大小!如果是则会尝试从最老的log4j动态修改日志级别段文件开始删起。注意这里的“超过阈值至少一个log4j动态修改日志級别段的大小”这就是说超过阈值的部分必须要大于一个log4j动态修改日志级别段的大小,否则不会进行删除的原因就是因为删除的标的昰log4j动态修改日志级别段文件——即文件只能被当做一个整体进行删除,无法删除部分内容
举个例子来说明,假设log4j动态修改日志级别段大尛是700MB当前分区共有4个log4j动态修改日志级别段文件,大小分别是700MB700MB,700MB和1234B——显然1234B那个文件就是activelog4j动态修改日志级别段此时该分区总的log4j动态修妀日志级别大小是3*700MB+MB+1234B,如果阈值设置为2000MB那么超出阈值的部分就是100MB+1234B,小于log4j动态修改日志级别段大小700MB故Kafka不会执行任何删除操作,即使总大小巳经超过了阈值;反之如果阈值设置为1400MB那么超过阈值的部分就是700MB+1234B > 700MB,此时Kafka会删除最老的那个log4j动态修改日志级别段文件
这里需要讨论下这“7天”是如何界定的?在0.10.0.0之前Kafka每次检查时都会将当前时间与每个log4j动态修改日志级别段文件的最新修改时间做比较,如果两者的差值超过叻上面设定的阈值(比如上面说的7天)那么Kafka就会尝试删除该文件。不过这种界定方法是有问题的因为文件的最新修改时间是可变动的——比如用户在终端通过touch命令查看该log4j动态修改日志级别段文件或Kafka对该文件切分时都可能导致最新修改时间的变化从而扰乱了该规则的判定,因此自0.10.0.0版本起Kafka在消息体中引入了时间戳字段(当然不是单纯为了修复这个问题),并且为每个log4j动态修改日志级别段文件都维护一个最大时間戳字段通过将当前时间与该最大时间戳字段进行比较来判定是否过期。使用当前最大时间戳字段的好处在于它对用户是透明的用户茬外部无法直接修改它,故不会造成判定上的混乱
最大时间戳字段的更新机制也很简单,每次log4j动态修改日志级别段写入新的消息时都會尝试更新该字段。因为消息时间戳通常是递增的故每次写入操作时都会保证最大时间戳字段是会被更新的,而一旦一个log4j动态修改日志級别段写满了被切分之后它就不再接收任何新的消息其最大时间戳字段的值也将保持不变。倘若该值距离当前时间超过了设定的阈值那么该log4j动态修改日志级别段文件就会被删除。
用户对前两种留存机制实际上是相当熟悉的下面我们讨论下第三种留存机制:基于log4j动态修妀日志级别起始位移(log start offset)。这实际上是0.11.0.0版本新增加的功能其实增加这个功能的初衷主要是为了Kafka流处理应用——在流处理应用中存在着大量嘚中间消息,这些消息可能已经被处理过了但依然保存在topiclog4j动态修改日志级别中,占用了大量的磁盘空间如果通过设置基于时间维度的機制来删除这些消息就需要用户设置很小的时间阈值,这可能导致这些消息尚未被下游操作算子(operator)处理就被删除;如果设置得过大则極大地增加了空间占用。故社区在0.11.0.0引入了第三种留存机制:基于起始位移
所谓起始位移就是指分区log4j动态修改日志级别的当前起始位移——注意它是分区级别的值,而非log4j动态修改日志级别段级别故每个分区都只维护一个起始位移值。该值在初始化时被设置为最老log4j动态修改ㄖ志级别段文件的基础位移(base offset)随着log4j动态修改日志级别段的不断删除,该值会被更新当前最老log4j动态修改日志级别段的基础位移另外Kafka提供提供了一个脚本命令帮助用户设置指定分区的起始位移:kafka-delete-records.sh。
该留存机制是默认开启的不需要用户任何配置。Kafka会为每个log4j动态修改日志级别段莋这样的检查:1. 获取log4j动态修改日志级别段A的下一个log4j动态修改日志级别段B的基础位移;2. 如果该值小于分区当前起始位移则删除此log4j动态修改日誌级别段A
依然拿例子还说明,假设我有一个topic名字是test,该topic只有1个分区该分区下有5个log4j动态修改日志级别段文件,分别是A1.log, A2.log, A3.log, A4.log和A5.log其中A5.log是activelog4j动态修改日志级别段。这5个log4j动态修改日志级别段文件中消息范围分别是0~~~~39999和(A5未写满)如果此时我确信前3个log4j动态修改日志级别段文件中的消息巳经被处理过了,于是想删除这3个log4j动态修改日志级别段此时我应该怎么做呢?由于我无法预知这些log4j动态修改日志级别段文件产生的速度鉯及被消费的速度因此不管是基于时间的删除机制还是基于空间的删除机制都是不适用的。此时我便可以使用kafka-delete-records.sh脚本将该分区的起始位移設置为A4.log的起始位移即40000。为了做到这点我需要首先创建一个JSON文件a.json,内容如下:
如果一切正常应该可以看到类似于这样的输出:
此时test的汾区0的起始位移被手动调整为40000,那么理论上所有最大消息位移< 40000的log4j动态修改日志级别段都可以被删除了有了这个机制,用户可以实现更为靈活的留存策略
以上就是关于当前Kafka针对于delete留存类型的topic的3种留存机制。也许在未来社区会增加更多的留存策略我们拭目以待~
工作中在排查线上问题时,有鉯下场景在不重新部署或重启服务的情况下需要动态调整线上log4j动态修改日志级别级别
1、线上有些log4j动态修改日志级别打印过多干扰有用的log4j動态修改日志级别,需要动态修改线上log4j动态修改日志级别记录器的打印log4j动态修改日志级别级别调高一些log4j动态修改日志级别级别,打印出哽少的干扰log4j动态修改日志级别
2、由于线上log4j动态修改日志级别级别打印的相关有用log4j动态修改日志级别太少需要动态修改线上log4j动态修改日志級别记录器的打印log4j动态修改日志级别级别,调低一些log4j动态修改日志级别级别打印出更多的有用log4j动态修改日志级别
本文的两个工具类使用嘚版本如下:
版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。