公眾號 : 倔強小獅子(最新發布)
- Kafka 中訊息是以 topic 進行分類的,生產者生產訊息,消費者消費訊息,都是面向 topic的。
topic 是邏輯上的概念
,而 partition 是物理上的概念,每個 partition 對應於一個 log 檔案,該 log 檔案中儲存的就是producer 生產的資料。Producer 生產的資料會被不斷追加到該log 檔案末端,且每條資料都有自己的 offset(偏移量)。消費者組中的每個消費者,都會實時記錄自己消費到了哪個 offset,以便出錯恢復時,從上次的位置繼續消費
- 圖細化 Topic->partition->segment
- 生產者不斷追加到 .log檔案末端(注意: .log檔案不是紀錄檔檔案,是資料檔案),為了防止資料量過大, 定位資料效率低下,Kafka 採取了分片和索引機制,將每個 partition 分為多個 segment。每個 segment對應兩個檔案——「.index」檔案和「.log」檔案。這些檔案位於一個資料夾下,資料夾命名規則為:規則為:topic 名稱+分割區序號。
注意 : index 和 log 檔案以當前 segment 的第一條訊息的 offset 命名
index 和 log 檔案講解(網上扒的圖,自己做的修改)
1.「.index」檔案儲存大量的索引資訊,「.log」檔案儲存大量的資料,索引檔案中的後設資料(可以描述資料的資料)指向對應資料檔案中
message 的物理偏移地址
(不要懵,偏移量是Kafka訊息的索引,而物理偏移量是Kafka偏移量的系統地址值)。
2. 注意 : Kafka 按照 二分查詢演演算法進行檢索資料,二分查詢演演算法百度百科
- 方便在叢集中擴充套件,一個 topic又可以有多個 Partition 組成
- 可以提高並行,因為可以以 Partition 為單位讀寫了。
- 我們需要將 producer 傳送的資料封裝成一個 ProducerRecord 物件
指明 partition 的情況下,直接將指明的值直接作為 partiton 值;
3. 沒有指明 partition 值但有 key 的情況下,將 key 的 hash 值與 topic 的 partition數進行取餘得到 partition 值
4. 既沒有 partition 值又沒有 key 值的情況下,第一次呼叫時隨機生成一個整數(後面每次呼叫在這個整數上自增),將這個值與 topic 可用的 partition 總數取餘得到 partition
值,也就是常說的 round-robin 演演算法
- 為保證 producer 傳送的資料,能可靠的傳送到指定的 topic,topic 的每個 partition 收到
producer 傳送的資料後,都需要向 producer 傳送 ack(acknowledgement 確認收到),如果producer 收到 ack,就會進行下一輪的傳送,否則重新傳送資料
方案 | 優點 | 缺點 |
---|---|---|
半數以上完成同步,就傳送 ack | 延遲低 | 選舉新的 leader 時,容忍 n 臺節點的故障,需要 2n+1個副本 |
全部完成同步,才傳送ack | 選舉新的 leader 時,容忍 n 臺節點的故障,需要 n+1 個副本 | 延遲高 |
- Kafka 選擇第二種方案
- 採用第二種方案後,設想下一個場景:leader 收到資料,所有 follower 都開始同步資料,但有一個 follower,因為某種故障,遲遲不能與 leader 進行同步,那 leader 就要一直等下去,直到它完成同步,才能傳送 ack。這個問題怎麼解決呢?
- Leader 維護了一個動態的 in-sync replica set (ISR),意為和 leader 保持同步的 follower 集合。當 ISR 中的 follower 完成資料的同步之後,leader 就會給 follower 傳送 ack。如果 follower長時間 未 向 leader 同 步 數 據 , 則 該 ollower 將 被 踢 出 ISR , 該 時 間 閾 值 由replica.lag.time.max.ms 引數設定。Leader 發生故障之後,就會從 ISR 中選舉新的 leader。
對於某些不重要的資料, 對資料的要求性不高的情況下,能夠容忍資料的丟失性,不需要等待 ISR 所有follower全部接收.所以Kafka提供了三種可靠性級別,可以根據專案業務的需求權衡
- 引數 0 : producer 不等待 broker 的 ack,這一操作提供了一個最低的延遲,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 發生故障,那麼會造成資料重複。(這裡所說的follower是ISR中的)
- LEO:每個副本的最後一個offset
- HW:指的是消費者能見到的最大的 offset,ISR 佇列中最小的 LEO。
- follower 發生故障後會被臨時踢出 ISR,待該 follower 恢復後,follower 會讀取本地磁碟記錄的上次的 HW,並將 log 檔案高於 HW 的部分擷取掉,從 HW 開始向 leader 進行同步。等該 follower 的 LEO 大於等於該 Partition 的 HW,即 follower 追上 leader 之後,就可以重
新加入 ISR 了。- leader 發生故障之後,會從 ISR 中選出一個新的 leader,之後,為保證多個副本之間的資料一致性,其餘的 follower 會先將各自的 log 檔案高於 HW 的部分截掉,然後從新的 leader
同步資料
注意:這隻能保證副本之間的資料一致性,並不能保證資料不丟失或者不重複。
將伺服器的 ACK 級別設定為-1,可以保證 Producer 到 Server 之間不會丟失資料,即 At Least Once 語意。相對的,將伺服器 ACK 級別設定為 0,可以保證生產者每條訊息只會被傳送一次,即 At Most Once 語意。
At Least Once 可以保證資料不丟失,但是不能保證資料不重複;相對的,At Least Once可以保證資料不重複,但是不能保證資料不丟失。但是,對於一些非常重要的資訊,比如說交易資料,下游資料消費者要求資料既不重複也不丟失,即 Exactly Once 語意。在 0.11 版本以前的 Kafka,對此是無能為力的,只能保證資料不丟失,再在下游消費者對資料做全域性去重。對於多個下游應用的情況,每個都需要單獨做全域性去重,這就對效能造成了很大影響。0.11 版本的 Kafka,引入了一項重大特性:冪等性。所謂的冪等性就是指 Producer 不論向 Server 傳送多少次重複資料,Server 端都只會持久化一條。冪等性結合 At Least Once 語意,就構成了 Kafka 的 Exactly Once 語意。
即:
At Least Once + 冪等性 = Exactly Once
要啟用冪等性,只需要將 Producer 的引數中enable.idompotence 設定為 true 即可。
Kafka的冪等性實現其實就是將原來下游需要做的去重放在了資料上游。開啟冪等性的 Producer 在初始化的時候會被分配一個 PID,發往同一Partition 的訊息會附帶 Sequence Number。而Broker 端會對<PID, Partition, SeqNumber>做快取,當具有相同主鍵的訊息提交時,Broker 只會持久化一條。
但是 PID 重新啟動就會變化,同時不同的 Partition 也具有不同主鍵,所以冪等性無法保證跨
分割區跨對談的 Exactly Once。
作者:專業於寫這些入門到深層知識,提升我們的基本功,期待你的關注,和我一起學習
轉載說明:未獲得授權,禁止轉載