kafka日誌清理策略,compact和delete

1. kafka日誌清理策略概述

kafka log的清理策略有兩種:delete,compact,默認是delete
這個對應了kafka中每個topic對於record的管理模式

  1. delete:一般是使用按照時間保留的策略,當不活躍的segment的時間戳是大於設置的時間的時候,當前segment就會被刪除
  2. compact: 日誌不會被刪除,會被去重清理,這種模式要求每個record都必須有key,然後kafka會按照一定的時機清理segment中的key,對於同一個key只保留罪行的那個key.同樣的,compact也只針對不活躍的segment
    配置爲
cleanup.policy: delete
cleanup.policy: compact

如果沒有特殊說明,本文中的配置均爲kafka-1.1, 且爲topic級別是設置

2. kafka segment

在學習日誌清理策略之前,首先了解一下kafka是如何存儲和管理日誌的,因爲他的管理都是基於segment的,所以有必要先了解清楚這個
segement的產生策略。

2.1 segmnet 的作用

  1. kafka的日誌存儲和消費,對外的最小粒度是partion,也就是producer和consumer最小的選擇粒度是某個topic的某些partition。
  2. 每個partition又多個segment組成,這些segment一般是按照時間順序產生的。
  3. 在單個partition中只有一個處於active的segment,這個segment是正在寫入的segment(假設爲segmentA),當segmentA的大小達到一定的程度(或者是經過了一定的時長),就會產生一個新的segmentB,這個時候segmentA就不再有數據寫入了,變成了不活躍的segment,而segmentB就是當前Active的segment.
  4. 日誌清理的策略總是針對不活躍的segment進行的。

2.2 segment生成相關的配置

  1. segment.bytes: 每個segment的大小,達到這個大小會產生新的segment, 默認是1G
  2. segment.ms: 配置每隔n ms產生一個新的segment,默認是168h,也就是7天

這兩個配置是同時起作用的,那個條件先滿足都會執行產生新的segment的動作
在這裏,我們就需要注意,需要理解這兩個配置在日誌的不同場景下可能帶來的影響,在下面介紹具體的日誌清理策略的時候會再回來看這一塊兒。

3. 日誌清理delete策略

3.1 delete 相關配置

假如對某個topic(假設爲user_topic)設置了 cleanup.policy: delete
那麼當前topic使用的log刪除策略就是 delete,這個策略會週期性的檢查partion中的不活躍的segment,根據配置採用兩種方式刪除一些舊的segment.

retention.bytes: 總的segment的大小限制,達到這個限制後會刪除舊的segment,默認值爲-1,就是不會刪除
retention.ms: segment的最後寫入record的時間-當前時間 > retention.ms 的segment會被刪除,默認是168h, 7天

一些其他的輔助性配置

log.retention.check.interval.ms: 每隔多久檢查一次是否有可以刪除的log,默認是300s,5分鐘 這個是broker級別的設置
file.delete.delay.ms: 在徹底刪除文件前保留的時間,默認爲1分鐘   這個是broker級別的設置

在delete的日誌策略下,我們來討論一下,假如我們想要日誌保留3天
我們可以通過設置

retention.ms: 259200000

假設我們保留其他的配置不便。想想一下這個場景:
日誌產生的很慢,3天還沒有達到1g,這個時候根據segment的產生策略,還只有一個segment,而且這個segment是活躍的,所以不能被刪除,即使到了第4天可能依然不能被刪除。這個時候如果我們依然想要優化存儲,就可以使用另一個配置來使刪除依然能夠按時觸發,對的,我們可以設置

segment.ms: 43200000 # 12個小時

這樣的話,每隔12個小時,只有有新的數據進來,都會產生一個新的segment,這樣的話,就可以觸發3天的刪除策略了。
所以,比較重要的一點是,對於流量比較低的topic,要注意控制 segment.ms< retention.ms

3.2 簡單總結

kafka啓用delete的清理策略的時候需要注意配置

cleanup.policy: delete
segment.bytes: 每個segment的大小,達到這個大小會產生新的segment, 默認是1G
segment.ms: 配置每隔n ms產生一個新的segment,默認是168h,也就是7天
retention.bytes: 總的segment的大小限制,達到這個限制後會刪除舊的segment,默認值爲-1,就是不會刪除
retention.ms: segment的最後寫入record的時間-當前時間 > retention.ms 的segment會被刪除,默認是168h, 7天

對於低流量的topic需要關注使用segment.ms 來配合日誌的清理

4. 日誌清理compact策略

4.1 日誌compact的使用場景

日誌清理的compact策略,對於那種需要留存一份全量數據的需求比較有用,什麼意思呢,比如,

我用flink計算了所有用戶的粉絲數,而且每5分鐘更新一次,結果都存儲到kafka當中。
這個時候kafka相當於是一個數據總線,任何需要用戶粉絲數的業務部門都可以從kafka中拿到這個數據。
這個時候如果數據的保存使用delete策略,爲了保存所有用戶的粉絲數,只能設置不刪除,也就是

retention.bytes: -1
retention.ms: Long.MAX #這個值需要自己去設置實際的數值值

這樣的話,數據會無限膨脹,而且,很多數據是無意義的,因爲業務方從kafka中消費數據的時候,實際上只是想知道用戶的當前粉絲數是多少,不關注一個月前這個用戶有多少粉絲數,但是這些數據都在kafka中存儲,會造成無意義的消費。
kafka提供了一種叫做compact的清理策略,這個策略可以很好的幫助我們應對這種情況。

kafka的compact 策略要求每個record都要有key,kafka是根據key來進行去重合並的。每個key至少保留一個最新的值。

4.2 compact的工作模式

對於每一個kafka partition的日誌,以segment爲單位,都會被分爲兩部分,已清理和未清理的部分。同時,未清理的那部分又分爲可以清理的和不可清理的。對於可以清理的segment大致是下面的一個清理思路。
在這裏插入圖片描述
同時對於清理過後的segment如果太小,kafka也會有一定的策略去合併這些segemnt,防止segment碎片化。
我們通過配置

cleanup.policy: compact

來開啓compact的日誌清理策略
配套的配置還有

  1. min.cleanable.dirty.ratio: 可以進行compact的髒數據的比例,dirtyRatio = dirtyBytes / (cleanBytes + dirtyBytes) 其中dirtyBytes表示可清理部分的日誌大小,cleanBytes表示已清理部分的日誌大小。這個配置也是爲了提升清理的性價比設置的,因爲清理數據需要對磁盤進行讀寫,開銷並不小,如果你的數據只有很小的重複比例,實際上是沒有清理的必要的。這個值默認是0.5 也就是髒了的數據達到了總數據的50%纔會清理,一般情況下我如果開啓了compact策略,都會將這個值設置爲0.1,感覺這樣對於想要消費當前topic的業務方更加友好。

  2. min.compaction.lag.ms: 這個設置了在一條消息在被produer發送到kafka當中之後,多久時間以內不會被compact,爲了滿足有些想要獲取一定時間內的歷史快照的業務,默認是0,就是不會根據消息投遞的時間來決定消息是否應該被compacted

4.3 tombstone 消息

在compact下,還有一類比較特殊的消息,只有key,value值爲null的消息,這一類消息如果合併了實際上也是沒有意義的,因爲沒有值,所以kafka在compact的時候會刪除value爲null的消息,但是並不是在第一次去重的時候立刻刪除,而是允許存儲的更久一些。有一個特殊的配置來處理。
delete.retention.ms: 這個配置就是專門針對tombstone類型的消息進行設置的。默認爲24小時,也就是這個tombstone在當次compact完成後並不會被清理,在下次compact的時候,他的最後修改時間+delete.retention.ms>當前時間,纔會被刪掉。

這裏面還有一點需要注意的是,如果你想測試tombstone的刪除功能的話,請注意不要使用console-producer,他並不能產生value爲null的record,坑死個人的,還是老老實實的用java-client跑一跑吧。

4.4 低流量topic的注意事項

同樣,因爲compact針對的是不活躍的segment,所以我們要對低流量的topic特別小心。
在流量較低的情況下。假如我們設置

segment.bytes: 每個segment的大小,達到這個大小會產生新的segment, 默認是1G
segment.ms: 配置每隔n ms產生一個新的segment,默認是168h,也就是7天

這樣的話,新的segment沒有辦法產生,也就無從進行compact了。

4.5 簡單總結compact的配置

kafka啓用delete的清理策略的時候需要注意配置

cleanup.policy: compact
segment.bytes: 每個segment的大小,達到這個大小會產生新的segment, 默認是1G
segment.ms: 配置每隔n ms產生一個新的segment,默認是168h,也就是7天
retention.bytes: 總的segment的大小限制,達到這個限制後會刪除舊的segment,默認值爲-1,就是不會刪除
retention.ms: segment的最後寫入record的時間-當前時間 > retention.ms 的segment會被刪除,默認是168h, 7天
min.cleanable.dirty.ratio: 髒數據可以容忍的比例,如果你的機器性能可以,而且數據量較大的話,建議這個值設置更小一些,對consumer更友好
min.compaction.lag.ms: 看業務有需要的話可以設置

對於低流量的topic需要關注使用segment.ms 來配合日誌的清理

5. kafka創建修改topic的命令

5.1. 創建topic的時候指定配置

#!/bin/bash


ZOOKEEPER="127.0.0.1:2181"
BROKER="127.0.0.1:9092"

TOPIC="post-count-processed"

## 刪除操作
../kafka_2.12-2.2.0/bin/kafka-topics.sh --bootstrap-server $BROKER  --delete --topic $TOPIC
sleep 3

echo "----------------------"

../kafka_2.12-2.2.0/bin/kafka-topics.sh --zookeeper ${ZOOKEEPER} --create --topic ${TOPIC} --partitions 1    --replication-factor 3  --config cleanup.policy=compact --config segment.ms=86400000 --config min.cleanable.dirty.ratio=0.1

5.2 topic創建時忘了設置,修改方式

#!/bin/bash

ZOOKEEPER="127.0.0.1:2181"
BROKER="127.0.0.1:9092"
TOPIC="post-count-processed"

./kafka_2.12-2.2.0/bin/kafka-configs.sh --zookeeper ${ZOOKEEPER} --entity-type topics --entity-name ${TOPIC}    --alter --add-config "delete.retention.ms=86400000,segment.ms=3600000,min.cleanable.dirty.ratio=0.1"

5.3 查看你的配置

#!/bin/bash

ZOOKEEPER="127.0.0.1:2181"
BROKER="127.0.0.1:9092"
TOPIC="post-count-processed"

../kafka_2.12-2.2.0/bin/kafka-configs.sh --zookeeper  ${ZOOKEEPER} --entity-type topics --entity-name ${TOPIC} --describe

參考
http://kafka.apache.org/11/documentation.html#compaction
https://www.linkedin.com/pulse/introduction-topic-log-compaction-apache-kafka-nihit-saxena
https://blog.csdn.net/u013332124/article/details/82793381

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章