1. Partition的作用
Topic是邏輯的概念,Partition是物理的概念:
- Partition 對一個 Topic 的消息進行物理上的分離,讓消息可以分布在不同的實體機器上,可以提升系統吞吐量和并行處理能力。
- 每個Partition可以有多個副本(Leader和Follower),Leader負責讀寫操作,Follower負責數據同步。將消息備份在副本中,可以確保高可用性。
舉個例子,更形象的理解Partition 和 Topic:
- Topic 比作高速公路,不同的 Topic就是不同的高速公路
- Partition 比作車道,有的公路是 3 車道,有的是 4 車道,車道可以提升公路的運輸能力
Partition的目的是:通過多Partition實現負載均衡的效果,提高kafka集群的吞吐率。
2. 消息寫入Partition
一個 Topic 有多個 Partition,生產者向一個 Topic 中發送消息的時候,有3種寫入方式:
- kafka默認輪詢規則
- producer指定partition key寫入特定的partition
- producer自定義規則
3. 消息消費
假設主題T1有四個分區。
3.1 一個消費群組
3.1.1 partition數量 > 消費者數量
只有一個消費者時,消費者1將收到所有分區的全部消息。
當有兩個消費者時,每個消費者將分別從兩個分區接受消息。
3.1.2 partition數量 = 消費者數量
當有四個消費者時,每個消費者都可以接受一個分區的消息。
3.1.3 partition數量 < 消費者數量
當有五個消費者時,會有閑置的消費者。
3.2 多個消費群組
消費者群組之間是互不影響的:
4. 分區分配策略
Kafka的分區分配策略決定了如何將Topic的各個Partition分配給消費者組內的消費者,以實現消息的并行消費。這些策略通過配置參數partition.assignment.strategy來指定。主要的分區分配策略包括:
- RangeAssignor(范圍分配器):
Kafka的默認分區分配策略。它首先將所有Partitions按分區編號排序,然后將消費者按字母順序排序。之后,將Partitions均勻地“分配”給消費者,盡量使每個消費者分配到連續的Partition區間。這種方式有利于保持消息的順序性,特別是在消費者組中的消費者數量少于或等于分區數時。 - RoundRobinAssignor(輪詢分配器):
這種策略將分區在消費者間進行輪詢分配,確保每個消費者盡可能平均地獲得相同數量的Partitions。相比RangeAssignor,它不保證分區的連續性,但能更好地分散負載,尤其是在消費者數量遠大于分區數的情況下。 - StickyAssignor(粘性分配器 / 粘性分配策略):
引入于Kafka 0.10.1版本,這是一種更高級的分配策略,旨在結合RangeAssignor和RoundRobinAssignor的優點。它試圖在重新平衡時保持分配的穩定性(即盡量保持之前分配給消費者的Partitions不變),同時確保分區盡可能均勻地分布在消費者之間。這種策略減少了頻繁的rebalance操作導致的性能開銷,提高了整體的穩定性。
5. 分區Rebalance
觸發分區分配策略的情景:
- 消費者組成員變化:當有新的消費者加入或已有消費者離開消費者組時,會觸發重新分配。
- 訂閱列表變化:如果消費者修改了其訂閱的Topic列表,也會引起分配策略的重新執行。
- Broker或Partition變化:Kafka集群的Broker增加、減少或Topic的分區數發生變化時,需要重新分配分區。
- Session超時:消費者長時間未發送心跳給組協調者(通常由Zookeeper或Kafka自身的GroupCoordinator服務擔任),被視為已離線,從而觸發再平衡。
- 手動觸發:在某些情況下,管理員或應用程序可以通過API調用來手動觸發消費者的再平衡。
每次觸發Rebalance時,Kafka會依據配置的分區分配策略重新計算分區到消費者的映射關系,以達到最佳的負載均衡狀態。但是也會消耗大量網絡資源和CPU資源,導致在Rebalance期間消費性能下降、集群不穩定,可能導致消息延遲、消息擠壓、消息重復消費等異常。為了緩解上述問題,通常采取的措施包括優化Rebalance觸發條件、合理配置消費者參數、使用更高效的分區分配策略(如StickyAssignor)、以及確保消費者及時提交偏移量等。