Kafka 會不會丟訊息?

2022-01-31 09:38:53 字數 2978 閱讀 9280

kafka 是分布式發布-訂閱訊息系統。它最初由 linkedin 公司開發,之後成為 apache 專案的一部分。

kafka 是乙個分布式的,可劃分的,冗餘備份的永續性的日誌服務。它主要用於處理活躍的流式資料。

kafka 的整體架構非常簡單,是顯式分布式架構,主要由 producer、broker(kafka)和 consumer 組成。

producer(生產者)可以將資料發布到所選擇的 topic(主題)中。生產者負責將記錄分配到 topic 的哪乙個 partition(分割槽)中。可以使用迴圈的方式來簡單地實現負載均衡,也可以根據某些語義分割槽函式(如記錄中的key)來完成。

consumer(消費者)使用乙個consumer group(消費組)名稱來進行標識,發布到 topic 中的每條記錄被分配給訂閱消費組中的乙個消費者例項。消費者例項可以分布在多個程序中或者多個機器上。

在討論 kafka 是否丟訊息前先來了解一下什麼是訊息傳遞語義。

message delivery semantic 也就是訊息傳遞語義,簡單說就是訊息傳遞過程中訊息傳遞的保證性。主要分為三種:

理想情況下肯定是希望系統的訊息傳遞是嚴格 exactly once,也就是保證不丟失、只會被處理一次,但是很難做到。

回到主角 kafka,kafka 有三次訊息傳遞的過程:

在這三步中每一步都有可能會丟失訊息,下面詳細分析為什麼會丟訊息,如何最大限度避免丟失訊息。

生產者是與 leader 直接互動,所以先從集群獲取 topic 對應分割槽的 leader 元資料;

獲取到 leader 分割槽元資料後直接將訊息發給過去;

kafka broker 對應的 leader 分割槽收到訊息後寫入檔案持久化;

follower 拉取 leader 訊息與 leader 的資料保持一致;

follower 訊息拉取完畢需要給 leader 回覆 ack 確認訊息;

kafka leader 和 follower 分割槽同步完,leader 分割槽會給生產者回覆 ack 確認訊息。

生產者採用 push 模式將資料發布到 broker,每條訊息追加到分割槽中,順序寫入磁碟。訊息寫入 leader 後,follower 是主動與 leader 進行同步。

kafka 訊息傳送有兩種方式:同步(sync)和非同步(async),預設是同步方式,可通過 producer.type 屬性進行配置。

kafka 通過配置 request.required.acks 屬性來確認 producer 的訊息:

如果 acks 配置為 0,發生網路抖動訊息丟了,生產者不校驗 ack 自然就不知道丟了。

如果 acks 配置為 1 保證 leader 不丟,但是如果 leader 掛了,恰好選了乙個沒有 ack 的 follower,那也丟了。

如果 acks 配置為 all 保證 leader 和 follower 不丟,但是如果網路擁塞,沒有收到 ack,會有重**的問題。

kafka broker 接收到資料後會將資料進行持久化儲存,你以為是下面這樣的:

沒想到是這樣的:

作業系統本身有一層快取,叫做 page cache,當往磁碟檔案寫入的時候,系統會先將資料流寫入快取中,至於什麼時候將快取的資料寫入檔案中是由作業系統自行決定。

kafka 提供了乙個引數 producer.type 來控制是不是主動 flush,如果 kafka 寫入到 mmap 之後就立即 flush 然後再返回 producer 叫同步 (sync);寫入 mmap 之後立即返回 producer 不呼叫 flush 叫非同步 (async)。

kafka 通過多分割槽多副本機制中已經能最大限度保證資料不會丟失,如果資料已經寫入系統 cache 中但是還沒來得及刷入磁碟,此時突然機器宕機或者掉電那就丟了,當然這種情況很極端。

消費者通過 pull 模式主動的去 kafka 集群拉取訊息,與 producer 相同的是,消費者在拉取訊息的時候也是找 leader 分割槽去拉取。

多個消費者可以組成乙個消費者組(consumer group),每個消費者組都有乙個組id。同乙個消費者組的消費者可以消費同一 topic 下不同分割槽的資料,但是不會出現多個消費者消費同一分割槽的資料。

消費者消費的進度通過 offset 儲存在 kafka 集群的 __consumer_offsets 這個 topic 中。

消費訊息的時候主要分為兩個階段:

標識訊息已被消費,commit offset座標;

處理訊息。

先 commit 再處理訊息。如果在處理訊息的時候異常了,但是 offset 已經提交了,這條訊息對於該消費者來說就是丟失了,再也不會消費到了。

先處理訊息再 commit。如果在 commit 之前發生異常,下次還會消費到該訊息,重複消費的問題可以通過業務保證訊息冪等性來解決。

那麼問題來了,kafka到底會不會丟訊息?答案是:會!

kafka可能會在三個階段丟失訊息:

生產者傳送資料;

kafka broker 儲存資料;

消費者消費資料;

在生產環境中嚴格做到 exactly once 其實是難的,同時也會犧牲效率和吞吐量,最佳實踐是業務側做好補償機制,萬一出現訊息丟失可以兜底。

kafka到底會不會丟訊息?

網上很多文章都有講解kafka是如何保證不丟失訊息的,但是真正的不丟訊息嗎?特別是當我看到broker寫訊息是寫入記憶體中,也就是作業系統頁快取中,我就在想,如果這個時候物理機重啟,記憶體東西都沒了,訊息不久沒有了嗎,於是帶著這個疑問去找了很多資料,我們今天就談談到底會不會丟訊息。生產者發訊息給br...

Kafka如何保證不丟訊息

生產者 producer 呼叫send方法傳送訊息之後,訊息可能因為網路問題並沒有傳送過去。訊息到partition的時候,會分配乙個offset,消費者拉取某個分割槽的訊息後,會自動提交offset,如果這部分訊息還沒有消費,突然掛掉了,這個時候這部分訊息就丟失了 kafka中partition分...

會不會孤單

上班的時候 忽然心裡特別難受 趴在桌子上哭了一會 很長時間了 心裡面一直堵堵的 不痛快 不單純因為失戀 當然 也是因為失戀 一年多的感情 猛的 走到頭了 想起來的時候總覺得一切好象是做夢 隱隱的有什麼事情發生過 卻又不知道到底是什麼 認識他的時候 我還在上學 和所有感情的開始一樣 甜蜜的 難捨難分的...