1. 程式人生 > 其它 >kafka學習(六)kafka核心設計原理

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
  • 提交過去的時候,keyconsumerGroupId+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就是利用分段+索引的方式來解決查詢效率的問題。