在使用Kafka的過程當中,分區是一個不可忽視的概念。不少時候你會帶着這樣的疑問:Kafka的分區該怎麼劃分?按什麼劃分?分多少個?撰稿之時,我在《深刻理解Kafka》一書中搜索了一下「分區」這個詞,結果發現出現的頻率至少有4位數之多。Kafka中分區的概念涉獵不少,好比:分區分配、分區重分配、失效分區等。在本公衆號裏也發表過幾篇文章來說述Kafka分區中的某些知識點:算法
本文並不延續講解這些內容,而是要劍走偏鋒,聊一聊Kafka分區被你們所忽視的一個隱藏屬性——消息的歸類。微信
在Kafka中主題和分區是兩個很是重要的概念。Kafka中的消息向來以「主題」來進行歸類(劃分),一個主題能夠包含若干個分區,一個分區只屬於單個主題。同一主題下的不一樣分區所包含的消息不一樣的(若是須要數據冗餘,那麼涉及到的是Kafka的多副本機制,這裏不展開論述)。對於單個分區而言,消息是順序追加的,也所以爲Kafka提供了分區內的順序特性,這一點在RabbitMQ不是太好保證(其實RabbitMQ也不是不能夠,就是有點麻煩)。性能
使用分區最主要的做用仍是提升可擴展性。若是一個主題只有一個分區,那麼全部的數據讀寫都通過這一個分區的話勢必會形成性能瓶頸。固然,若是規定主題只能有一個分區的話,那麼分區這個概念就能夠去除掉了。若是主題有多個分區,那麼能夠將這種讀寫的壓力分散開來。主題中的多個分區不必定要在同一個broker上,徹底能夠分佈在多個broker上,特殊狀況下還能夠一個分區一個broker。設計
「消息的歸類」並非不是主題所獨有的特性,其實分區也能夠,分區能夠看作是消息的二次歸類,讓分區變得有意義。舉個例子,咱們建立了一個主題用來存儲人員信息,這我的員信息就是對數據的一種歸類。因爲人員衆多,咱們想着是要用多個分區來分攤一下讀寫壓力,那麼咱們能夠依據什麼來劃分呢?第一種,按照生肖,這樣就能夠建立12個分區,分區編號從0開始分別表明鼠、牛、虎、兔、牛等等,這樣的分區規則就是對人員信息的二次歸類。第二種,咱們估算12個分區的壓力也有點頂不住,那麼咱們能夠按照姓名拼音的首字母來劃分,這也是二次歸類。3d
在實際實踐時能夠將消息(ProducerRecord<生肖,人員信息>)對應的key設置爲與其對應分區的「歸類類別」便可。好比,按生肖分,那麼「屬牛的肥朝」能夠這一條消息(人員信息)能夠表示爲:key=「牛」,value=「姓名:肥朝,特長:帥」。cdn
聰明的同窗還會接着想到用姓氏來歸類。。也不是不可行,中國百家姓(其實何止)。可是要考慮到一種狀況就是數據傾斜,「趙錢孫李」所對應的分區確定比「令狐」、「獨孤」、「上官」之類的分區所承擔的數據負載要多不少,這樣嚴重的數據傾斜會致使服務總體效能的下降。「趙錢孫李」能夠視爲熱點數據,而「令狐」、「獨孤」、「上官」能夠視爲冷數據,咱們能夠這樣劃分,參考下圖: blog
在某些時候,按照字面的類別劃分也很難避免數據傾斜。沿用上面的例子,宋朝時期,姓趙的人實在太多,劃分到一個分區仍是會有嚴重的數據傾斜,那麼就須要對這一姓氏作多一些處理,多化幾個分區給它。token
舉這些例子是爲了說明:若是要讓分區得到「二次歸類」的特性,就須要作好「二次歸類」的準備,也就是須要應對數據熱點問題。爲了儘量的數據分佈均勻而弱化熱點問題應該根據歸類的特性作好合理的規劃。圖片
在Kafka中建立消息的時候,若是不指定分區,那麼就會根據消息的key來進行計算。get
若是key不爲null,那麼默認的分區器會對key進行哈希(採用MurmurHash2算法,具有高運算性能及低碰撞率),最終根據獲得的哈希值來計算分區號,擁有相同key的消息會被寫入同一個分區。若是key爲null,那麼消息將會以輪詢的方式發往主題內的各個可用分區。前者根據key進行計算,潛在的使用了「二次歸類」這個特性,後者採用輪詢的方式,潛在的丟棄了「二次歸類」的特性。
固然,咱們還能夠自定義Kafka中的分區器來實現隨機的分類,這個實現很簡單,從[0,分區數)中挑選一個整數而已,如此也一樣會丟棄「二次歸類」的特性。
關於分區的這個屬性,你還有什麼須要補充的嗎?不妨在留言去留言來一塊兒探討。
歡迎支持筆者小冊:《圖解Kafka之實戰指南》和《圖解Kafka之核心原理》
歡迎支持筆者新做:《深刻理解Kafka:核心設計與實踐原理》和《RabbitMQ實戰指南》,同時歡迎關注筆者的微信公衆號:朱小廝的博客。