天天看點

淺談Kafka的分區

單純地将Kafka了解為消息總線(Message Bus)并不全面,它除了能提供快速、可擴充、高可用(Kafka的高可用不一定需要分布式的多節點來實作)且持續的基于釋出/訂閱模式的總線服務外,你還可以把它看作可分布式的備援的日志送出服務。

在Kafka消息總線中,消息的生産者和消費者是嚴格分隔開的,而任何用戶端可以在Kafka消息緩存釋放前(預設是7天,不管消息有沒有被消費過)重播任何總線消息。

淺談Kafka的分區

将Kafka視為日志送出服務的話,每一個資料流對應一個Topic,每一個Topic可以有多個Partition,Partition是每個Topic的全量副本,存放在任意一台Broker伺服器上,伺服器與Partition是一對多的關系,而每個Partition隻能被一個消費者(跨Group情況除外)消費。

淺談Kafka的分區

消息的生産者并不關心消息被分到幾個Partition,但生産者會給消息配上私鑰(Key),在傳輸時Kafka通過計算私鑰的哈希值決定它屬于哪個Partition,同時消息有先後順序,且不能調整。沒有私鑰的消息會以輪詢機制(Round Robin)投遞。

淺談Kafka的分區

當然,我們上面也說到不同的Partition是給到不同的消費者的,是以我們也可以定制查詢讓特定的消息進入特定的Partition。

淺談Kafka的分區

這樣看起來,在partition這裡就能完成目标消費者的精準投遞,那面對多個消費者(組)的情況,我隻要多建幾個partition就可以了麼?

情況并非如此簡單。

首先,越多的Partition意味着越多的吞吐量。不管在生産端還是消費端,消息到所有Partition的寫入都是同步進行的,一些複雜的運算(比如資料壓縮)就會占用更多的硬體資源。

其次,越多的Partition需要越多的檔案句柄(Open File Handles)。每個Partition都将一個目錄映射給Kafka Broker,在這個日志目錄中,每個日志分段(Segment)會有兩類檔案--索引和實際資料。目前的版本而言,Kafka Baoker會打開這兩類檔案的舉兵。是以越多的Partition就以為着在Broker的系統層有越多的OpenFiles。當然,這隻是個配置問題,實際環境中Kafka叢集中每個Broker可以同時運作超過三萬個檔案句柄。

越多的Partition會降低可用性,盡管Kafka支援叢集内複制,一個partition可以在跨broker的節點上存放多副本(Leader & Follower,見下圖)

淺談Kafka的分區

我們知道一般情況下,一個Broker發生了問題或正常關閉,zookeeper會及時發現并将Leader移至其他Broker節點。

淺談Kafka的分區

那麼問題來了,如果broker程序非正常關閉(比如使用“kill -9程序号”方式關閉)對于zookeeper來說就沒那麼容易恢複了。而如果此時我還有2000個partition隊列,受影響的broker承擔了其中400個partition的leader角色,那可用性就會大受影響了。

越多的Partition會增加端到端的延時。端到端的延遲指的是從生産者釋出消息到消費者讀取消息所花的時間,這其中涉及到送出偏移量(committed offset)的問題。實驗資料顯示,從一個broker複制1000個partition可以增加20毫秒的延時,這對一些實時性要求極高的消費者而言是幾乎不可接受的。

淺談Kafka的分區

繼續閱讀