broker能夠理解成一個kafka服務node,是一個運行的kafka服務。broker與broker之間是平等的關係,任意broker均可以down機而不影響其餘broker正常工做。kafaka在啓動的時候,會將本身的信息同步到zk上。數據存儲使用了zk的零時節點,broker須要經過心跳機制維護與zk的註冊關係,一旦broker宕機,zk上面對應的零時節點也會被刪除。
咱們能夠把controller當成集羣的管理者,集羣中borker啓動時若是沒有controller回主動的去zk上註冊znode節點來搶奪controller的位置,註冊成功的broker會被當選爲kafka controller。若當前的controller宕機其餘borker會從從新進入controller爭搶流程,從而選出新的controller。controller主要的功能以下:html
Zookeeper的/brokers/topics
下建立znode來觸發建立邏輯,而controller會監聽該path下的變動來執行真正的「建立topic」邏輯。/admin/delete_topics/<topic>
節點來觸發刪除topic,controller執行真正的邏輯/admin/reassign_partitions
節點來觸發,controller負責按照方案分配分區/admin/preferred_replica_election
寫數據,controller提取數據執行preferred leader分配Topic至關於傳統消息系統MQ中的一個隊列queue,能夠把topic當成是消息的分類。partiton能夠當作是topic的一個分區,目的是突破IO瓶頸。kafka在存儲topic日誌的時候,將topic分開存儲,這樣就能將同一個消息的寫壓力分配到不一樣的分區,這樣能夠提高kafka的總體吞吐能力。爲了保證數據的高可用,kafka使用partiton-Replica進行數據備份,若partition leader掛了,kafka controller會自動從partiton-Replica選舉新的leader。提到備份不得不提到ISR,這是一個同步備份列表,每當用戶添加新的消息時,分區leader成功寫入日誌後,後必須保證ISR列表裏面的備份也成功寫入日誌後,才能給客戶端相應成功。所以ISR列表的備份的日誌老是和leader保持一致,在leader宕機的時候,可使用ISR列表的備份取代leader的位置。node
kafka最終的數據承載是經過log的方式進行,kafka會按照請求的順序將消息存儲到log中。咱們知道一個topic可能會被分配到到個分區partiton來減輕單點負載。每一個partiton實際上在寫log的時候也會存在,單個文件大小物理極限的問題。所以kafka引入了segment解決方案,即將日誌分段存儲。不一樣的segment log組合起來的數據就是分區的存儲消息數據。爲了方便經過offset定位消息,segment log使用first-offset格式進行文件命名,first-offset是該文件存儲的第一條消息的offset。這樣就能經過消費者提供的offset很快定位到文件,而後經過offset偏移量能夠快速定位消息的存儲位置。apache
生產者負責消息的發送,生產者須要指定消息的topic來區分不一樣消息。kafka收到消息後經過loadbalance策略,使用hash(message) % topic分片數
決定將數據存儲到哪個分片。 而後將message發送到制定分片的leader,leader收到消息後,將消息保存下來,接着等待ISR(a set of in-sync replicas,該列表的備份數據時刻保持和leader數據一致)中的replica消費消息併發送ack,若ISR列表中的備份分區都已經確認收到消息並保存成功後,leader將成功的消息返回給producer以代表,消息被妥善保存。併發
與其餘消息系統不一樣的是:kafka不會複製去保存客服端以前消費了那條消息,以及下一條應當消費那條消息,kafka將這些工做交給了消費客服端來作,所以kafka在消息消費能夠作到無狀態。offset就是用來保存某個消費組(consumer group)消費的在當前分區日誌下的偏移量的。一般狀況下,多個客服端在同時消費同一個消息分區消息的時候會存在併發問題,對於offset的控制就會出現問題,這樣就會出現消費重複的狀況,kafka使用無鎖機制解決這個問題。kafka規定,同一個分區(partition)下的數據只能被通一個consumer group中的一個線程消費,這樣就避免了不一樣線程之間爭奪通一個資源,經過這種設計kafka作到了無鎖,這樣能夠避免鎖競爭形成效率降低。所以建議consumer group裏面的線程數應當和分區數保持一致,這樣作能夠有效的利用線程資源,線程多了會被浪費掉,少了一個線程可能會處理多個分區的數據。若是你須要多個業務消費同一個消息,因爲不一樣的consumer group對贊成主題分區的offset是分開存儲的,咱們能夠建立多個consumer group實現多個線程來消費同一個消息的目的。.net
寫數據:經過上面消息的存儲過程能夠發現,除了數據存儲和備份操做,並無其餘耗時操做。路由分區->leader寫數據->數據複製,這些操做都和現有數據規模沒有任何關係。每次寫數據只會在原來的基礎上作追加存儲。因爲kafka使用了順序存儲而不是非隨機存儲(聽說磁盤的順序存儲效率遠高於磁盤的隨機存儲、有時候甚至比內存的隨機寫效率還高),同時kafka還使用了批量存儲的方式減小了對io的操做,提高了io效率。
讀數據:consumer在消費某個topic的時候,消費者會將全部的分區數據消費完,kafka要求,同一時刻對同一分區的數據只會被一個線程消費,這樣避免了鎖操做。同時經過consumer group提供的offset數據,經過kafka的文件存儲機制能夠快速的定位到一個segment文件,而且經過計算offset偏移量能夠快速定位到數據。從整個消費流程來看,數據規模對每一個過程效率是不敏感的。線程
高可用的解決方案一般是採用數據冗餘以及快速恢復來解決的。kafka經過分區數據備份(partition replica)&分區數據分散到不一樣的機器以及kafka controller能夠快速檢測到宕機節點,經過讀取節點的分區數據,能夠快速從新選取分區leader,以恢復故障。同時在故障的處理過程當中,就算該分區不可用,不往分區寫入數據便可,對kafka的數據讀取也是沒有影響的。kafka使用hash 取餘的目的在於均衡負載,並不在於爲了經過message能夠快速的查找到這個message所在位置,這個不是kafka關注的業務。kafka經過數據複製和快速恢復作到了高可用,同時基於message不關注經過某個具體message的具體存存儲位置,所以在擴展kafka的時候,或者在擴展消息分區的時候,不須要進行額爲的數據複製操做,下降了擴展時候的成本。設計
更多文章能夠訪問jframe.cn日誌