kafka學習(六)kafka核心設計原理
一、Kafka核心總控制器
定義:kafka叢集中的一個負責管理所有分割槽和副本的狀態的broker。
PS:kafka單臺機器也叫叢集。
職能:選舉新的leader副本、ISR變更通知所有broker更新其元資料、讓新分割槽被其他節點感知。
- 當某個分割槽的leader副本出現故障時,由控制器負責為該分割槽選舉新的leader副本。
- 當檢測到某個分割槽的ISR集合發生變化時,由控制器負責通知所有broker更新其元資料資訊。
- 當使用kafka-topics.sh指令碼為某個topic增加分割槽數量時,同樣還是由控制器負責讓新分割槽被其他節點感知到。
Controller選舉原理
- kafka叢集啟動時,每個borker去ZK上建立一個“/controller 臨時節點”,誰建立成功誰就是Controller。
- 當這個controller角色的broker宕機了,此時ZK上的臨時節點會消失,叢集裡其他broker會一直監聽這個臨時節點,發現臨時節點消失了,就競爭再次建立臨時節點,ZK又會保證只有一個broker成為新的controller。
Partition副本選舉Leader原理
- controller感知到分割槽leader所在的broker掛了,則會從ISR列表裡挑第一個broker作為leader。
- 若引數unclean.leader.election.enable為true,代表在ISR列表裡所有副本都掛了,則可以在ISR列表以外的副本中選leader。
副本進入ISR的條件
- 副本節點不能產生分割槽,必須能與zookeeper保持會話以及跟leader副本網路連通。
- 副本能複製leader上的所有寫操作,並且不能落後太多。
PS:之所以取ISR中的第一個broker升級Leader,是因為第一個broker最先放進ISR 列表,可能是同步資料最多的副本。
二、消費者offset記錄機制
offset記錄機制
- 每個consumer會定期將自己消費分割槽的offset提交給kafka內部topic:__consumer_offsets。
- 提交過去的時候,key是consumerGroupId+topic+分割槽號,value就是當前offset的值。
- kafka會定期清理topic裡的訊息,最後就保留最新的那條資料。
PS:因為__consumer_offsets可能會接收高併發的請求,kafka預設給其分配50個分割槽(可以通過offsets.topic.num.partitions設定),這樣可以通過加機器的方式抗大併發。
三、消費者Rebalance機制
Rebalance機制
定義:如果消費組裡的消費者數量有變化或消費的分割槽數有變化,kafka會重新分配消費者和消費分割槽的關係。
PS:每個消費者都會有消費組,如果不指定會生成預設的組。
PS:rebalance只針對subscribe這種不指定分割槽消費的情況,如果通過assign這種消費方式指定了分割槽,kafka不會進行rebanlance。
PS:rebalance過程中,消費者無法從kafka消費訊息!!!【儘量避免在系統高峰期時發生重平衡。】
觸發場景:
- 1、消費組裡的consumer增加或減少了
- 2、動態給topic增加了分割槽
- 3、消費組訂閱了更多的topic
Rebalance過程
設計原理:分割槽方案制定過程中有兩個組長,消費者組長負責制訂分割槽策略,生產者組長負責通知其他消費者分割槽策略。【同一個消費者組中的消費者沒有聯絡,需要通過kafka組長來協調。】
兩個重要角色:
- 組協調器【生產者組長】:每個消費者組都會選擇一個broker作為自己的組協調器coordinator,負責監控這個消費組裡的所有消費者的心跳,以及判斷是否宕機,然後開啟消費者rebalance。
- 消費組協調器【消費者組長】:負責制定分割槽方案,並與組協調器進行通訊。
PS:消費者組長不是我們所說的分割槽Leader!這個概念要區分好!
第一階段:選擇組協調器【生產者組長】
消費者組中的每個consumer啟動時會向kafka叢集中的某個節點傳送查詢組協調器的請求,並跟其建立網路連線。
組協調器選擇方式
公式:hash(consumer_group_id) % _consumer_offsets主題的分割槽數。
根據公式獲取到分割槽地址後,這個分割槽leader對應的broker就是這個消費者組的組協調器。
第二階段:消費者入組
在成功找到消費組所對應的組協調器後就進入消費組入組的階段,在此階段的消費者會向組協調器傳送入組請求。
組協調器從一個消費者組中選擇第一個加入group的consumer作為消費者組長,把消費者組的情況傳送給這個broker,接著這個broker會負責制定分割槽方案。
第三階段:組協調器下發分割槽方案
消費者組長通過給組協調器傳送下發分割槽策略請求,接著組協調器就把分割槽方案下發給各個consumer,他們會與指定分割槽的leader對應的broker進行網路連線以及訊息消費。
Rebalance分割槽分配策略
- range【預設】:根據分割槽數/消費者數量,然後給每個消費者分配n個分割槽。【消費者1:0~3 消費者2:4~6 消費者3:7~9】
- round-robin:輪詢分配機制。【消費者1:0、3、6 消費者2:1、4、7 消費者3:2、5、8】
- sticky:粘性輪詢機制。【當分割槽增加或者增加消費者時,只會重新分配掛掉的那臺或者新的分割槽。】
PS:range和輪詢當分割槽增加或者增加消費者時,會重新輪詢。而粘性策略則不會,粘性策略只會重新分配掛掉的那臺或者新的分割槽。
四、生產者釋出訊息機制
寫入方式
producer採用push模式將訊息釋出到broker,每條訊息都被append到patition中,屬於順序寫磁碟。
PS:順序寫磁碟效率比隨機寫記憶體要高,可以保障kafka吞吐量。
訊息路由
producer傳送訊息到broker時,會根據分割槽演算法選擇將其儲存到哪一個partition。其路由機制為:
- 1、指定了patition,則直接使用。
- 2、未指定patition但指定key,通過對key的value進行hash選出一個patition。【key的組成見本文上半部分的解析】
- 3、patition和key都未指定,使用輪詢選出一個 patition。
寫入流程
五、高水位
基本概念
- HW:高水位
- LEO:日誌末端位移
HW即一個partition對應的ISR中最小的LEO(log-end-offset), consumer最多隻能消費到HW所在的位置。
每個replica都有HW,leader和follower各自負責更新自己的HW的狀態。
PS:對於leader新寫入的訊息,consumer不能立刻消費,leader會等待該訊息被所有ISR中的replicas同步後更新HW,此時訊息才能被consumer消費。
快樂圖解~
六、日誌分段儲存原理
Kafka一個分割槽的訊息資料對應儲存在一個資料夾下,以topic名稱+分割槽號命名:
訊息在分割槽內是分段(segment)儲存,每個段的訊息都儲存在不一樣的log檔案裡,這種特性方便old segment file快速被刪除,kafka規定了一個段位的log文 件最大為1G,做這個限制目的是為了方便把 log 檔案載入到記憶體去。
# 【部分訊息的offset索引檔案】,kafka每次往分割槽發4K(可配置)訊息就會記錄一條當前訊息的offset到index檔案 # 如果要定位訊息的offset會先在這個檔案裡快速定位,再去log檔案裡找具體訊息 00000000000000000000.index
# 【訊息儲存檔案】,主要存offset和訊息體 00000000000000000000.log
# 【訊息的傳送時間索引檔案】,kafka每次往分割槽發4K(可配置)訊息就會記錄一條當前訊息的傳送時間戳與對應的offset到timeindex檔案 # 如果需要按照時間來定位訊息的offset,會先在這個檔案裡查詢 00000000000000000000.timeindex 00000000000005367851.index 00000000000005367851.log 00000000000005367851.timeindex 00000000000009936472.index 00000000000009936472.log 00000000000009936472.timeindex
這個partition有三組segment檔案,當儲存滿時每個log檔案的大小是一樣的,但是儲存的message數量是不一定相等的(每條的message大小不一致)。
PS:每個日誌段檔案最大為1G。
- 檔案的命名是以該segment最小offset來命名的,如00000000000000.index儲存offset為0~5367850的訊息...以此類推。
- kafka就是利用分段+索引的方式來解決查詢效率的問題。