「請你簡述一下Kafka中的分區分配」,當面試官問你這個問題的時候,你會怎麼回答?其實,這道題目裏面就暗藏洶涌,由於Kafka中的分區分配在多處出現,而這個問題的表述方式是在潛意識裏暗示你回答一種,這樣在你自認爲很完美的回答完這個問題以後,面試官會冷不丁的來一句:還有呢?面試
當你回答完一個點的時候,面試官來一句還有呢,當你再補上一個的時候,他仍是會來一句還有呢,就算你又補上第三個的時候,他仍是會來一句還有呢?這個時候你會不會一臉懵逼?算法
今天就針對這個問題來告訴你們怎麼樣回答才能嚴絲合縫地搶得先機。bash
在Kafka中,分區分配是一個很重要的概念,卻每每會被讀者忽視,它會影響Kafka總體的性能均衡。當遇到「分區分配」這個字眼的時候,必定要記住有三處地方,分別是生產者發送消息、消費者消費消息和建立主題。雖然這三處的對應操做均可以被稱之爲「分區分配」,可是其實質上所包含的內容卻並不相同。微信
在面對開篇的問題的時候,不如一下就進行總結性的陳詞,說有三處,第1、第2、第三balabala,當真的讓你講完三處的時候,時間也就差很少了。。聰明的面試官看到你一上來就作了一個規劃總結,那他頂多也就讓你說說你最熟悉的一種,其實說不定心裏已經確認你是對的人。負載均衡
下面針對這三處作個講解。不過本文旨在羅列相關知識點,進行相關性的科普描述,讓讀者能夠追根溯源,但並不陳述具體細節,由於細節不少,篇幅有限,若有須要請詳參老朽的《深刻理解Kafka》。性能
對於用戶而言,當調用send方法發送消息以後,消息就天然而然的發送到了broker中。其實在這一過程當中,有可能還要通過攔截器、序列化器和分區器(Partitioner)的一系列做用以後才能被真正地發往broker。spa
producer.send(record);
複製代碼
消息在發往broker以前是須要肯定它所發往的分區的,若是消息ProducerRecord中指定了partition字段,那麼就不須要分區器的做用,由於partition表明的就是所要發往的分區號。若是消息ProducerRecord中沒有指定partition字段,那麼就須要依賴分區器,根據key這個字段來計算partition的值。分區器的做用就是爲消息分配分區。設計
Kafka中提供的默認分區器是DefaultPartitioner,它實現了Partitioner接口(用戶能夠實現這個接口來自定義分區器),其中的partition方法就是用來實現具體的分區分配邏輯:code
public int partition(String topic, Object key, byte[] keyBytes,
Object value, byte[] valueBytes, Cluster cluster);
複製代碼
默認狀況下,若是消息的key不爲null,那麼默認的分區器會對key進行哈希(採用MurmurHash2算法,具有高運算性能及低碰撞率),最終根據獲得的哈希值來計算分區號,擁有相同key的消息會被寫入同一個分區。若是key爲null,那麼消息將會以輪詢的方式發往主題內的各個可用分區。cdn
注意:若是key不爲null,那麼計算獲得的分區號會是全部分區中的任意一個;若是key爲null而且有可用分區,那麼計算獲得的分區號僅爲可用分區中的任意一個,注意二者之間的差異。
在Kafka的默認規則中,每個分區只能被同一個消費組中的一個消費者消費。消費者的分區分配是指爲消費組中的消費者分配所訂閱主題中的分區。
如圖所示,某個主題中共有4個分區(Partition):P0、P一、P二、P3。有兩個消費組A和B都訂閱了這個主題,消費組A中有4個消費者(C0、C一、C2和C3),消費組B中有2個消費者(C4和C5)。按照Kafka默認的規則,最後的分配結果是消費組A中的每個消費者分配到1個分區,消費組B中的每個消費者分配到2個分區,兩個消費組之間互不影響。每一個消費者只能消費所分配到的分區中的消息。
對於消費者的分區分配而言,Kafka自身提供了三種策略,分別爲RangeAssignor、RoundRobinAssignor以及StickyAssignor,其中RangeAssignor爲默認的分區分配策略,至於這三種策略具體表明什麼含義,能夠去查閱相關資料,好比《深刻理解Kafka》,嘿嘿。固然也能夠經過實現ParitionAssignor接口來自定義分區分配策略。
在消費組中若是有多個消費者,那麼這些消費者又可能會採用不一樣的分配策略,那麼最後怎麼「拍板」使用哪種具體的分配策略呢?
對於這裏,我想留一道思考題給你們:在Kafka的默認規則中,每個分區只能被同一個消費組中的一個消費者消費,那麼這個規則能夠被打破麼?若是能夠,怎麼打破?打破的收益又是什麼?
生產者的分區分配是指爲每條消息指定其所要發往的分區,消費者中的分區分配是指爲消費者指定其能夠消費消息的分區,而這裏的分區分配是指爲集羣制定建立主題時的分區副本分配方案,即在哪一個broker中建立哪些分區的副本。分區分配是否均衡會影響到Kafka總體的負載均衡,具體還會牽涉到優先副本等概念。
在建立主題時,若是使用了replica-assignment參數,那麼就按照指定的方案來進行分區副本的建立;若是沒有使用replica-assignment參數,那麼就須要按照內部的邏輯來計算分配方案了。使用kafka-topics.sh腳本建立主題時的內部分配邏輯按照機架信息劃分紅兩種策略:未指定機架信息和指定機架信息。若是集羣中全部的broker節點都沒有配置broker.rack參數,或者使用disable-rack-aware參數來建立主題,那麼採用的就是未指定機架信息的分配策略,不然採用的就是指定機架信息的分配策略。
歡迎支持筆者小冊:《圖解Kafka之實戰指南》和《圖解Kafka之核心原理》
歡迎支持筆者新做:《深刻理解Kafka:核心設計與實踐原理》和《RabbitMQ實戰指南》,同時歡迎關注筆者的微信公衆號:朱小廝的博客。