歷史性難題——如何為Kafka挑選合適的分割槽數?
作者:朱小廝
來源:朱小廝的部落格
如何為Kafka挑選合適的分割槽數?很多人都為這個問題傷過腦筋。
從吞吐量方面考慮,增加合適的分割槽數可以很大程度上提升整體吞吐量,但是超過對應的閾值之後吞吐量不升反降。如果應用對吞吐量有著一定程度上的要求,建議在投入生產環境之前對同款硬體資源做一個完備的吞吐量相關的測試,以找到合適的分割槽數閾值期間。
在建立完主題之後,雖然我們還是能夠增加分割槽的個數,但是基於key計算的主題需要嚴謹對待。當生產者向Kafka中寫入基於key的訊息時,Kafka通過訊息的key來計算出訊息將要寫入到哪個具體的分割槽中,這樣具有相同key的資料可以寫入到同一個分割槽中。Kafka的這一功能對於一部分應用是即為重要的,比如日誌壓縮。
再比如對於同一個key的所有訊息,消費者需要按訊息的順序進行有序的消費,如果分割槽的數量發生變化,那麼有序性就得不到保證。在建立主題時,最好能夠確定好分割槽數,這樣也可以省去後期增加所帶來的多餘操作。尤其對於與key高關聯的應用,在建立主題時可以適當地多建立一些分割槽,以滿足未來的需求。通常情況下,可以根據未來2年內的目標吞吐量來設定分割槽數。當然如果應用與key弱關聯,並且也具備便捷的增加分割槽數的操作介面,那麼也可以不用考慮那麼長遠的目標。
有些應用場景會要求主題中的訊息都能保證順序性,這種情況下在建立主題時可以設定分割槽數為1,這樣通過分割槽有序性的這一特性來達到主題有序性的目的。
當然分割槽數也不能一昧地增加,分割槽數會佔用檔案描述符,而一個程序所能支配的檔案描述符是有限的,這個也是我們通常意義上所說的檔案控制代碼的開銷。雖然我們可以通過修改配置來增加可用檔案描述符的個數,但是凡事總有一個上限,在選擇合適的分割槽數之前,最好再考量一下當前Kafka程序中已經使用的檔案描述符的個數。
分割槽數的多少還會影響系統的可用性。
Kafka通過多副本機制來實現叢集的高可用和高可靠,每個分割槽都會有一至多個副本,每個副本分別存在於不同的broker節點上,並且只有leader副本對外提供服務。在Kafka叢集的內部,所有的副本都採用自動化的方式進行管理,並確保所有的副本中的資料都能保持一定程度上的同步。當broker發生故障時,對於leader副本所宿主的broker節點上的所有分割槽將會暫時處於不可用的狀態,此時Kafka會自動的在其他的follower副本中選舉出新的leader用於接收外部客戶端的請求,整個過程由Kafka控制器負責完成。分割槽進行leader角色切換的過程中會變得不可用,不過對於單個分割槽來說這個過程非常的短暫,對於使用者而言可以忽略不計。但是如果叢集中的某個broker節點宕機,那麼就會有大量的分割槽需要同時進行leader角色切換,這個切換的過程將會耗費一筆可觀的時間,並且在這個時間視窗內這些分割槽也會變得不可用。
假如,一個3節點的Kafka叢集中存在3000個分割槽,每個分割槽擁有3個數據副本。當其中一個broker節點宕機時,所有1000個分割槽同時變得不可用。假設每一個分割槽恢復時間是5ms,那麼1000個分割槽的恢復時間將會花費5秒鐘。因此,在這種情況下,使用者將會觀察到系統存在5秒鐘的不可用時間視窗。可以適當地增加一些broker節點來減少單broker節點所負荷的分割槽,進而降低單broker節點故障引起的短期服務不可用的影響。
如果宕機的broker節點恰好又是Kafka叢集的控制器時,在控制器被重新選舉到新的broker節點之前這些分割槽leader角色切換的過程是不會開始進行的。雖說控制器的恢復(重新選舉新的控制器)也是自動進行的,整體上不會有太大的問題,但是新的控制器需要載入叢集中所有的元資料資訊,其中就包括了所有的分割槽資訊,分割槽數越多載入的耗時就會越長,進而拖慢了控制器的恢復進度,最終也就拖慢了分割槽服務的恢復進度。
分割槽數越多也會讓Kafka的正常啟動和關閉的耗時變得越長,與此同時,主題的分割槽數越多不僅會增加日誌清理的耗時,而且在被刪除時也會耗費更多的時間。對於舊版的生產者和消費者客戶端而言,分割槽數越多也會增加它們的開銷,不過這一點在新版的生產者和消費者客戶端中有效地得到了抑制。
如何選擇合適的分割槽數?
從某種意思來說,考驗的是決策者的實戰經驗,更透徹地來說,是對Kafka本身、業務應用、硬體資源、環境配置等多方面的考量而做出的抉擇。在設定完分割槽數,或者更確切的說是建立完主題之後,還要對其追蹤、監控、調優以求更改更好的利用它。讀者看到本文的內容之前或許沒有對分割槽數有太大的困擾,可能看完之後反而困惑了起來,其實大可不必太過驚慌,一般情況下,根據預估的吞吐量以及是否與key相關的規則來設定分割槽數即可,後期可以通過增加分割槽數、增加broker或者分割槽重分配等手段來進行改進。如果一定要給一個準則的話,筆者給的一個建議是分割槽數設定為叢集中broker的倍數,即假定叢集中有3個broker節點,可以設定分割槽數為3、6、9等,至於倍數的選定可以參考預估的吞吐量。不過,如果叢集中的broker節點數有很多,比如大幾十或者上百、上千,這種準則也不太適用,在選定分割槽數時進一步的可以引入基架等參考因素。
對於這個問題,網上也有很多的資料,筆者也看過,由於版本更迭,現在只能贊同其中的部分內容。本文也是筆者對分割槽數抉擇的小小認知,如果你對此問題有相同或者相反的意見,歡迎在留言區探討。
-END-
近期熱文:
為什麼Kafka中的分割槽數只能增加不能減少?
一文帶你吃透執行緒池
設計一個百萬級的訊息推送系統
Hmily:高效能非同步分散式事務TCC框架
並行化:你的高併發大殺器
Spring Boot整合 Sentry 監控專案日誌
重磅:Elasticsearch上市!市值近50億美元
利用SPRING管理熱載入的GROOVY物件!
Spring Boot中如何擴充套件XML請求和響應的支援
Java 11正式釋出,新特性解讀
關注我
點選“閱讀原文”,看本號其他精彩內容