1. 程式人生 > 實用技巧 >2:kafka架構

2:kafka架構

1、kafka工作流程和檔案儲存機制

  • kafka中訊息是以topic進行分類的,生產者生產訊息,消費者消費訊息都是面向topic的;
  • topic是邏輯上的概念,而partition是物理上的概念,每個partition對應一個log檔案,檔案中儲存的就是producer生產的資料。會不斷追加到檔案末端,媒每條資料都有自己的offset,消費者也會記錄自己消費到了哪個offset.以便出錯時從上次的位置繼續消費;
    在這裡插入圖片描述
  • 為防止log檔案過大導致資料定位效率低下,kafka採取了分片和索引機制,將每個partition分為多個segment。每個segment對應兩個檔案:index檔案和log檔案,位於一個資料夾下,資料夾的命名是topic名稱+分割槽序號。index和log檔案是以當前segment的第一條訊息的offset命名。

在這裡插入圖片描述
index檔案儲存大量的索引資訊,log檔案儲存大量資料,索引檔案中的元資料指向對應資料檔案中的message的物理偏移地址。

2、kafka生產者

2.1 分割槽策略

為什麼分割槽

方便在叢集中擴充套件
可以提高併發:以分割槽為單位讀寫;

分割槽原則

將producer傳送的資料封裝成一個ProducerRecord物件;
在這裡插入圖片描述

  • 指明partition的話,直接將其作為partition值;
  • 未指定partition的話,將key的hash值%(partition數量)得到partition值;
  • 若key和partition都沒有,使用round-robin演算法,第一次呼叫時隨機生成一個整數(後面每次呼叫在這個整數上自增),將這個值與topic的可用的分割槽數取餘。

資料可靠性保證

為保證producer傳送的資料,能可靠的傳送到指定的topic,topic的每個partition收到資料後,需要向producer傳送ack,如果producer收到ack,就會進行下一輪的傳送,否則重新發送資料;
在這裡插入圖片描述

副本資料同步策略

方案優點缺點
半數以上完成同步延遲低選舉新的leader時,容忍n臺節點的故障需要2n+1個副本
全部同步完成 才傳送ACK選舉新的leader時容忍n臺節點的故障需要n+1個副本延遲高

kafka使用第二種方案原因如下:

  • 為了容忍n臺節點的故障,第一種方案需要2n+1個副本,第二種只需要n+1個副本,kafka的每個分割槽都有大量的資料,第一種方案造成大量冗餘;
  • 第二種方案網路延遲較高,但是網路延遲對kafka的影響較小;

ISR(in-sync replica set)
  對於第二種情況:leader收到資料,所有follower都開始同步資料,但是有一個follower,因為某種故障,遲遲不能與leader進行同步,那麼leader就要一直等下去直到完成同步才能傳送ack。怎麼解決呢:
leader維護了一個動態的in-sync replica set(ISR),即和leader保持同步的follower集合。當ISR中的follower完成資料的同步之後,leader給follower傳送ack,若是follower長時間沒有向leader傳送同步資料,則該follower將會被踢出ISR。leader發生故障之後將會從ISR這選舉新的leader;

ACK應答機制
對於某些不太重要的資料,對資料的可靠性要求不是很高,能夠容忍資料的少量丟失,沒必要等ISR的follower全部接收成功;
kafka為使用者提供了三種可靠性級別。通過對acks引數進行配置:

  • 0:producer不等待broker的ack,這一操作提供了一個最低的延遲,broker故障時可能丟失資料;
  • 1:producer等待broker的ack,partition的leader落盤成功後返回ack,如果在follower同步成功之前leader故障,將會丟失資料;
    在這裡插入圖片描述
  • -1(all):producer等待broker的ack,partition的leader和follower全部落盤成功後返回ack。如果在follower同步完成後,broker傳送ack之前leader發生故障,會造成資料重複;
    在這裡插入圖片描述

故障處理細節

LEO(log end offset):每個副本的最後一個offset
HW(high watermark):所有副本中最小的LEO
在這裡插入圖片描述

(1)follower故障
follower發生故障後會被臨時踢出ISR,待該follower恢復後,follower會讀取本地磁碟記錄的上次的HW,將log檔案中高於HW的部分擷取掉,從HW開始向leader進行同步。等該follower的LEO大於等於該partition的HW,即follower追上leader之後就可以重新加入ISR了。
(2)leader故障
leader發生故障之後,會從ISR中選出一個新的leader,其餘的follower會先將各自的log檔案高於H的部分截掉,從新的leader中同步資料;

exactly once語義

  • 將伺服器的ACK級別設定為-1,可以保證producer到server之間不會丟失資料 即at least once語義;
  • 將伺服器ACK級別設定為0,可以保證生產者每條訊息只會被髮送一次即At Most Once語義;
  • At Least Once可以保證資料不丟失,但是不能保證資料不重複;相對的, At Least Once可以保證資料不重複,但是不能保證資料不丟失。
  • 對於一些非常重要的資訊,比如交易資料,下游資料消費者要求資料既不重複也不丟失;即Exactly once語義。在0.11版本之前對此是無能為力的,只能保證資料不丟失,再在下游消費者對資料進行全域性去重。
  • 0.11版本的kafka,引入了一項重大特性:冪等性。不論producer向server傳送多少次重複資料,server端只會持久化一條。
    At Least Once+冪等性=Exactly Once

3、kafka消費者

3.1 消費方式

consumer採用pull模式從broker中讀取資料;

push模式的不足是:

push模式很難適應消費速率不同的消費者,因為訊息傳送速率是由broker決定的;broker的目標是儘可能以最快的速率傳遞訊息,很容易造成consumer來不及處理訊息,造成拒絕服務以及網路阻塞。pull模式可以根據consumer的消費能力以適當的速率消費訊息;

pull模式的不足:

如果kafka沒有資料,消費者可能會陷入迴圈中,一直返回空資料。
解決:kafka消費者在消費資料時會傳入一個時長引數timeout,如果當前沒有資料可以消費,consumer會等待timeout後再返回;

3.2 分割槽分配策略

一個消費者組中有多個消費者,一個topic有多個分割槽,必然涉及到分割槽的分配問題;

kafka有兩種分配策略,RoundRobin和Range:
RoundRobin
在這裡插入圖片描述
range
在這裡插入圖片描述

3.3 offset的維護

由於consumer在消費過程中可能會出現斷電宕機等故障,consumer恢復後,需要從故障前的位置繼續消費,所以consumer需要實時記錄自己消費到了哪個offset,以便故障恢復後繼續消費;
kafka0.9版本之前,consumer預設將offset儲存在zookeeper中,從0.9版本開始consumer預設將offset儲存在kafka一個內建的topic中,該topic為__consumer_offsets。

3.4 kafka高效讀寫資料

順序寫磁碟
  生產者生產的資料需要寫入到log檔案,一致追加到檔案末尾,為順序寫。官網資料表明,同樣的磁碟順序寫能到600M/s,隨機寫只有100k/s。
零複製技術
kafka中的消費者在讀取服務端的資料時,需要將服務端的磁碟檔案通過網路傳送到消費者程序,網路傳送需要經過幾種網路節點。
在這裡插入圖片描述
通常情況下,kafka的訊息會有多個訂閱者,生產者釋出的訊息會被不同的消費者多次消費,為了優化這個流程,kafka使用了零拷貝技術:
在這裡插入圖片描述
零拷貝技術只用將磁碟檔案的資料複製到頁面快取一次,然後將資料從頁面快取直接傳送到網路中,避免了重複複製操作。

3.5 zookeeper在kafka的作用

kafka叢集中有一個broker會被選舉為controller,負責管理叢集broker的上下線、所有topic的分割槽副本分配和leader選舉等工作;controller的管理工作都是依賴於zookeeper的;