1. 程式人生 > >如何選擇合適的Topics、Partitions數量

如何選擇合適的Topics、Partitions數量

轉載自:http://blog.csdn.net/xiao_jun_0820/article/details/52573535

越多的分割槽可以提供更高的吞吐量

       首先需要明白以下事實:在kafka中,單個patition是kafka並行操作的最小單元。在producer和broker端,向每一個分割槽寫入資料是可以完全並行化的,此時,可以通過加大硬體資源的利用率來提升系統的吞吐量,例如對資料進行壓縮。在consumer端,kafka只允許單個partition的資料被一個consumer執行緒消費。因此,在consumer端,每一個Consumer Group內部的consumer並行度完全依賴於被消費的分割槽數量。綜上所述,通常情況下,在一個Kafka叢集中,partition的數量越多,意味著可以到達的吞吐量越大。
可以粗略地通過吞吐量來計算kafka叢集的分割槽數量。假設對於單個partition,producer端的可達吞吐量為p,Consumer端的可達吞吐量為c,期望的目標吞吐量為t,那麼叢集所需要的partition數量至少為max(t/p,t/c)。在producer端,單個分割槽的吞吐量大小會受到批量大小、資料壓縮方法、 確認型別(同步/非同步)、複製因子等配置引數的影響。經過測試,在producer端,單個partition的吞吐量通常是在10MB/s左右。在consumer端,單個partition的吞吐量依賴於consumer端每個訊息的應用邏輯處理速度。因此,需要對consumer端的吞吐量進行測量。
雖然能夠對分割槽的數量進行新增,但是對於基於Key來生成的這一類訊息需要重點關注。當producer向kafka寫入基於key的訊息時,kafka通過key的hash值來確定訊息需要寫入哪個具體的分割槽。通過這樣的方案,kafka能夠確保相同key值的資料可以寫入同一個partition。kafka的這一能力對於一部分應用是極為重要的,例如對於同一個key的所有訊息,consumer需要按訊息的順序進行有序消費。如果partition的數量發生改變,那麼上面的有序性保證將不復存在。為了避免上述情況發生,通常的解決辦法是多分配一些分割槽,以滿足未來的需求。通常情況下,需要根據未來1到2年的目標吞吐量來設計kafka的分割槽數量。
一開始可以基於當前的業務吞吐量為kafka叢集分配較小的broker數量,隨著時間的推移,可以向叢集中增加更多的broker,然後採用線上方式將適當比例的partition轉移到新增加的broker中去。通過這樣的方法,可以在滿足各種應用場景(包括基於key訊息的場景)的情況下,保持業務吞吐量的擴充套件性。

越多的分割槽需要開啟更多地檔案控制代碼

在kafka的broker中,每個分割槽都會對應著檔案系統的一個目錄。在kafka的資料日誌檔案目錄中(即每個分割槽對應的目錄),每個日誌資料段都會分配兩個檔案,一個索引檔案和一個數據檔案。當前版本的kafka,每個broker會為每個日誌段檔案開啟一個index檔案控制代碼和一個數據檔案控制代碼。因此,隨著partition的增多,需要底層作業系統配置更高的檔案控制代碼數量限制。這更多的是一個配置問題。

更多的分割槽會導致更高的不可用性

Kafka通過多副本複製技術,實現kafka叢集的高可用和穩定性。每個partition都會有多個數據副本,每個副本分別存在於不同的broker。所有的資料副本中,有一個數據副本為Leader,其他的資料副本為follower。在kafka叢集內部,所有的資料副本皆採用自動化的方式進行管理,並且確保所有的資料副本的資料皆保持同步狀態。
不論是producer端還是consumer端發往partition的請求,皆通過leader資料副本所在的broker進行處理。當broker發生故障時,對於leader資料副本在該broker的所有partition將會變得暫時不可用。Kafka將會自動在其他資料副本中選擇出一個leader,用於接收客戶端的請求。這個過程由kafka controller節點broker自動完成,主要是從Zookeeper讀取和修改受影響partition的一些元資料資訊。
在通常情況下,當一個broker有計劃地停止服務時,那麼controller會在服務停止之前,將該broker上的所有leader一個個地移走。由於單個leader的移動時間大約只需要花費幾毫秒,因此從客戶層面看,有計劃的服務停機只會導致系統在很小時間視窗中不可用。(注:在有計劃地停機時,系統每一個時間視窗只會轉移一個leader,其他leader皆處於可用狀態。)
然而,當broker非計劃地停止服務時(例如,kill -9方式),系統的不可用時間視窗將會與受影響的partition數量有關。假如,一個2節點的kafka叢集中存在2000個partition,每個partition擁有2個數據副本。當其中一個broker非計劃地宕機,所有1000個partition同時變得不可用。假設每一個partition恢復時間是5ms,那麼1000個partition的恢復時間將會花費5秒鐘。因此,在這種情況下,使用者將會觀察到系統存在5秒鐘的不可用時間視窗。
更不幸的情況發生在宕機的broker恰好是controller節點時。在這種情況下,新leader節點的選舉過程在controller節點恢復到新的broker之前不會啟動。Controller節點的錯誤恢復將會自動地進行,但是新的controller節點需要從zookeeper中讀取每一個partition的元資料資訊用於初始化資料。例如,假設一個kafka叢集存在10,000個partition,從zookeeper中恢復元資料時每個partition大約花費2ms,則controller的恢復將會增加約20秒的不可用時間視窗。
通常情況下,非計劃的宕機事件發生的情況是很少的。如果系統可用性無法容忍這些少數情況的場景,最好是將每個broker的partition數量限制在2,000到4,000,每個kafka叢集中partition的數量限制在10,000以內。

越多的分割槽可能增加端對端的延遲

Kafka端對端延遲定義為producer端釋出訊息到consumer端接收訊息所需要的時間,即consumer接收訊息的時間減去producer釋出訊息的時間。Kafka只有在訊息提交之後,才會將訊息暴露給消費者。例如,訊息在所有in-sync副本列表同步複製完成之後才暴露。因此,in-sync副本複製所花時間將是kafka端對端延遲的最主要部分。在預設情況下,每個broker從其他broker節點進行資料副本複製時,該broker節點只會為此工作分配一個執行緒,該執行緒需要完成該broker所有partition資料的複製。經驗顯示,將1000個partition從一個broker到另一個broker所帶來的時間延遲約為20ms,這意味著端對端的延遲至少是20ms。這樣的延遲對於一些實時應用需求來說顯得過長。
注意,上述問題可以通過增大kafka叢集來進行緩解。例如,將1000個分割槽leader放到一個broker節點和放到10個broker節點,他們之間的延遲是存在差異的。在10個broker節點的叢集中,每個broker節點平均需要處理100個分割槽的資料複製。此時,端對端的延遲將會從原來的數十毫秒變為僅僅需要幾毫秒。
根據經驗,如果十分關心訊息延遲問題,限制每個broker節點的partition數量是一個很好的主意:對於b各broker節點和複製因子為r的kafka叢集,整個kafka叢集的partition數量最好不超過100*b*r個,即單個partition的leader數量不超過100.

總結
       通常情況下,kafka叢集中越多的partition會帶來越高的吞吐量。但是,必須意識到叢集的partition總量過大或者單個broker節點partition過多,都會對系統的可用性和訊息延遲帶來潛在的影響。