面試官在考查你Kafka知識的時候極可能會故弄玄虛的問你一下:Kafka中的選舉時怎麼回事?除非問你具體的哪一種選舉,不然問這種問題的面試官多半也是對Kafka只知其一;不知其二,這個時候就是「弄死」他的時候。固然若是你沒有必定的知識儲備,那麼就是你被「弄死」的時候。面試
通常問這個問題,那麼他確定知道其中的一種,好比分區leader的選舉。所謂分區leader的選舉就是當ISR中的leader副本歇菜了,再從新選舉一個的過程。對於這個問題就是你反客爲主的機會,由於Kafka中的選舉有多處,可不止分區leader的選舉這一處,就算指明問分區leader的選舉,那麼也須要分4種狀況具體分析。而這裏面的細節是大多數人不甚明瞭的。算法
Kafka中的選舉大體能夠分爲三大類:控制器的選舉、分區leader的選舉以及消費者相關的選舉,這裏還能夠具體細分爲7個小類。咱們一一來過一下,本文只是簡單羅列下大體的內容,至於內部具體的細節邏輯就須要靠讀者本身去探索啦。虐人仍是被虐就靠你的自驅力了。bash
在Kafka集羣中會有一個或多個broker,其中有一個broker會被選舉爲控制器(Kafka Controller),它負責管理整個集羣中全部分區和副本的狀態等工做。好比當某個分區的leader副本出現故障時,由控制器負責爲該分區選舉新的leader副本。再好比當檢測到某個分區的ISR集合發生變化時,由控制器負責通知全部broker更新其元數據信息。微信
Kafka Controller的選舉是依賴Zookeeper來實現的,在Kafka集羣中哪一個broker可以成功建立/controller這個臨時(EPHEMERAL)節點他就能夠成爲Kafka Controller。網站
這裏須要說明一下的是Kafka Controller的實現仍是至關複雜的,涉及到各個方面的內容,若是你掌握了Kafka Controller,你就掌握了Kafka的「半壁江山」。篇幅所限,這裏就不一一展開了,有興趣的讀者能夠查閱一下《深刻理解Kafka》中第6章的相關內容。spa
這裏不說什麼一致性協議(PacificA)相關的內容,只講述具體的選舉內容。scala
分區leader副本的選舉由Kafka Controller 負責具體實施。當建立分區(建立主題或增長分區都有建立分區的動做)或分區上線(好比分區中原先的leader副本下線,此時分區須要選舉一個新的leader上線來對外提供服務)的時候都須要執行leader的選舉動做。設計
基本思路是按照AR集合中副本的順序查找第一個存活的副本,而且這個副本在ISR集合中。一個分區的AR集合在分配的時候就被指定,而且只要不發生重分配的狀況,集合內部副本的順序是保持不變的,而分區的ISR集合中副本的順序可能會改變。注意這裏是根據AR的順序而不是ISR的順序進行選舉的。這個提及來比較抽象,有興趣的讀者能夠手動關閉/開啓某個集羣中的broker來觀察一下具體的變化。code
還有一些狀況也會發生分區leader的選舉,好比當分區進行重分配(reassign)的時候也須要執行leader的選舉動做。這個思路比較簡單:從重分配的AR列表中找到第一個存活的副本,且這個副本在目前的ISR列表中。cdn
再好比當發生優先副本(preferred replica partition leader election)的選舉時,直接將優先副本設置爲leader便可,AR集合中的第一個副本即爲優先副本。
Kafka中有不少XX副本的稱呼,若是不是很瞭解,能夠關注本系列的下一篇《Kafka科普系列 | Kafka中到底有多少種副本?》
還有一種狀況就是當某節點被優雅地關閉(也就是執行ControlledShutdown)時,位於這個節點上的leader副本都會下線,因此與此對應的分區須要執行leader的選舉。這裏的具體思路爲:從AR列表中找到第一個存活的副本,且這個副本在目前的ISR列表中,與此同時還要確保這個副本不處於正在被關閉的節點上。
對於這部份內容的理解,額。。若是你對消費者、消費組、消費者協調器以及組協調器不甚理解的話,那麼。。。職能毛遂自薦《深刻理解Kafka》一書了,嘿嘿。
組協調器GroupCoordinator須要爲消費組內的消費者選舉出一個消費組的leader,這個選舉的算法也很簡單,分兩種狀況分析。若是消費組內尚未leader,那麼第一個加入消費組的消費者即爲消費組的leader。若是某一時刻leader消費者因爲某些緣由退出了消費組,那麼會從新選舉一個新的leader,這個從新選舉leader的過程又更「隨意」了,相關代碼以下:
//scala code.
private val members = new mutable.HashMap[String, MemberMetadata]
var leaderId = members.keys.head
複製代碼
解釋一下這2行代碼:在GroupCoordinator中消費者的信息是以HashMap的形式存儲的,其中key爲消費者的member_id,而value是消費者相關的元數據信息。leaderId表示leader消費者的member_id,它的取值爲HashMap中的第一個鍵值對的key,這種選舉的方式基本上和隨機無異。整體上來講,消費組的leader選舉過程是很隨意的。
插播:近日發現文章被盜的厲害,發文幾個小時文章就在各大門戶網站上出現,全都是標的原創。雖然沒有能力制止,可是我發現大多不仔細看直接抄的(有連我下面的公衆號二維碼也抄了去的,固然也有用PS來P掉我圖片水印的雞賊操做),因此機智的我。。不如在文章中插播一下個人書,讓他們盜了去也好替我宣傳宣傳。我是皮的很~~
到這裏就結束了嗎?還有分區分配策略的選舉呢。
許你對此有點陌生,可是用過Kafka的同窗或許對partition.assignment.strategy(取值爲RangeAssignor、RoundRobinAssignor、StickyAssignor等)這個參數並不陌生。每一個消費者均可以設置本身的分區分配策略,對消費組而言須要從各個消費者呈報上來的各個分配策略中選舉一個彼此都「信服」的策略來進行總體上的分區分配。這個分區分配的選舉並不是由leader消費者決定,而是根據消費組內的各個消費者投票來決定的。至於具體的細節麼。。。嘿嘿。
歡迎支持筆者小冊:《圖解Kafka之實戰指南》和《圖解Kafka之核心原理》
歡迎支持筆者新做:《深刻理解Kafka:核心設計與實踐原理》和《RabbitMQ實戰指南》,同時歡迎關注筆者的微信公衆號:朱小廝的博客。