常規配置
常規配置指的是一些在使用單機安裝時可以直接使用的默認值,這可以滿足大部分的開發需求。但是在部署到其他環境時,需要格外小心,這些參數是單個服務器最基本的配置,他們中的大部分需要經過修改之后才可以用在生產環境里
-
broker.id
每個broker都需要有一個標識符,使用broker.id來表示。默認值為0,在部署到生產環境時,這個broker.id在集群中需要是唯一的,一般可以使用host的名字縮寫來代替。 -
port
kafka啟動的時候監聽的端口,默認是9092。可以任意指派,但是不要小於1024,否則需要管理員權限,不建議。 -
zookeeper.connect
kafka的通信是基於zookeeper的,kafka的元數據保存在zookeeper中。connect可以指定一個zookeeper列表,格式為:hostname:port/path。這里的path使用默認值chroot比較好,官網提示使用chroot是最佳實踐。可以使用zookeeper列表來保證zookeeper和kafka之間的高可用。 -
log.dirs
kafka把所有的消息都保存在磁盤上,log.dirs就是指定保存在磁盤上的哪個目錄。如果有多個dir,kafka會根據“最少使用原則“,就是哪個目錄下面子目錄最少就在哪個目錄下面新增分區。 -
num.recovery.threads.per.data.dir
kafka會在如下三種情況下啟用可配置的線程池來處理日志片段:- 服務器正常啟動,需要打開每個分區的日志片段
- 服務器崩潰后重啟,需要檢查和截短每個分區的日志片段
- 服務器正常關閉,需要關閉日志片段
默認情況下,每個日志目錄只是用一個線程,因為這些線程只是在服務器啟動和關閉的時候會用到,所以完全可以設置大量的線程來加快這一過程。
這個參數的意思是每個分區路徑開幾個線程。比如log.dir有三個路徑,這個參數配置了8,那么恢復那三個目錄,就需要一共24個線程。
- auto.create.topics.enable
默認值是true,表示自動創建主題。默認情況下,kafka會在下面幾種情況下創建主題:- 生產者開始寫入消息
- 消費者開始讀取消息
- 客戶端向主題發送元數據
很多時候,這些行為都是非預期的。而且根據kafka協議,如果一個主題不先被創建,根本無法知道它是否已經存在。
如果想要顯式的創建主題,而不是自動創建,可以設置該值為false。
主題的默認配置
除了上面的kafka的常規配置外。針對創建出來的主題,也是需要進行配置的。可以通過管理工具為每個主題單獨配置一些參數,實現定制化或者優化,比如:分區個數、數據保留策略。
服務器提供的默認配置可以作為基准,默認值適用於大部分使用場景。
- num.partitions
指定新創建的主題將包含多少個分區。自動創建主題的時候,該值就是新創建主題的分區數。
kafka通過分區來實現對主題的橫向擴展,所以當有新的broker進入同一個topic的broker集群的時候,可以通過分區個數來實現集群的負載均衡。
設置該值的幾個依據:- 主題需要多大的吞吐量?例如:希望每秒鍾寫入100kb還是1gb?
- 從單個分區讀取數據的最大吞吐量是多少?每個分區一般都會有一個消費者,如果是消費者是寫數據庫操作,那么一般速度不會超過50mb每秒,那么也就代表從一個分區讀取數據的最大吞吐量不需要超過50mb每秒
- 可以通過類似於上面的方法來對生產者的寫入吞吐量來進行估算。不過一般生產者會比消費者的吞吐量大,因為很多數據是不需要處理或者是很多系統的並發結果
- 每個broker包含的分區個數,可用的磁盤空間、網絡帶寬
- 如果消息是按照不同的鍵來寫入分區的,那么為已有的主題新建分區就會很困難,因為這意味着需要修改代碼才能讓消息進入新增的分區
- 單個broker對分區的數量大小是有限制的,因為分區越多,占用的內存越多,完成首領選舉的時間也越長
下面是一個計算例子:
如果估算出來讀取和寫入主題的速度大概是每秒1gb,每個消費者每秒可以處理50mb數據,那么可以算出來需要至少20個分區。這樣就可以讓20個消費者同時讀取,從而達到每秒鍾1GB的吞吐量。ps:書上說:如果不知道這些信息,那么根據經驗,把分區的大小限制在25GB以內可以得到比較理想的效果。
- log.retention.ms
kafka根據時間來決定數據將會被保留多久。默認使用log.retention.hours參數來配置時間,默認值為168小時,也就是一周。除此以外,還有其他兩個參數log.retenion.minutes和log.retention.ms
坑:根據時間保留數據是通過檢查磁盤上日志片段文件的最后修改時間來實現的。一般來說,最后修改時間就是日志片段的關閉時間,也就是文件里最后一個消息的時間戳。如果使用管理工具在服務器間移動分區,最后修改時間就不准確了。時間誤差可能導致這些分區過多的保留數據。
- log.retention.bytes
除了使用時間限制保留的消息之外,還可以通過消息的字節數來判斷消息是否過期。它的值通過參數retention.bytes來指定,作用在每一個分區上。也就是說,如果有一個包含8個分區的主題,並且該參數被設置為1GB,那么這個主題最多可以保留8GB的數據。所以當主題的分區個數增加時,整個主題可以保留的數據也隨之增加。
這個參數可以和上面的時間參數搭配使用,那個提前到達,都會直接刪除到達刪除條件的消息。
- log.segment.bytes
以上的設置都作用在日志片段上,而不是作用在單個消息上。當消息到達broker時,他們被追加到分區的當前日志片段上。當日志片段大小達到log.segment.bytes時,當前日志片段就會關閉,等待過期,並會重新開啟一個日志片段,這個參數的值越小,就會越頻繁的關閉和分配新文件,從而降低磁盤寫入的整體效率。
如果主題的消息量不大,那么如何調整這個參數的大小就變得尤為重要。例如,如果一個主題每天只接受100mb的消息,而log.segment.bytes使用默認設置,那么需要10天時間才能填滿一個日志片段。因為在日志片段被關閉之前消息是不會過期的,所以如果log.retention.ms被設置為一周,那么日志片段最多需要在17天才會過期。而不是一周的時間,因為根據配置的過期時間,還需要在保留7天時間。
ps:使用時間戳獲取偏移量。在使用時間戳獲取日志偏移量時,kafka會檢查分區里最后修改時間大於指定時間戳的日志片段(已經被關閉的),該日志片段的前一個文件的最后修改時間小於指定時間戳,然后,kafka返回該日志片段開頭的偏移量。對於使用時間戳獲取偏移量的操作來說,日志片段越小,結果越准確。
- log.segment.ms
該參數指定了日志片段多長時間被關閉。和上面的一樣,兩者同時存在的情況下,容量和時間哪個先到達上線,日志片段就會被關閉。
ps:對於那些長時間達不到日志上限的,可以通過這個參數來關閉文件分區。如果打開文件過多,會導致磁盤性能受到影響。
- message.max.bytes
broker通過設置該參數來限制單個消息的大小,默認值是1mb。如果生產者嘗試發送的消息大於該值,那么消息不僅不會被接收,還會受到一個broker返回的錯誤信息。這個大小是消息壓縮后的大小。
這個值對參數有顯著的影響。值越大,那么負責處理網絡連接和請求的線程就需要花越多的時間來處理這些請求。他還會增加磁盤寫入塊的大小,從而影響IO吞吐量。
ps:消費者客戶端設置的fetch.message.max.bytes必須與服務器端設置的消息大小進行協調。如果這個值比message.max.bytes小,那么消費者就無法讀取比較大的消息,導致出現消費者被阻塞的情況。在為集群里的broker配置replica.fetch.max.bytes參數時,也遵循同樣的原則。