kafka 是分布式發布-訂閱訊息系統。它最初由 linkedin 公司開發,之後成為 apache 專案的一部分。kafka 的整體架構非常簡單,是顯式分布式架構,主要由 producer、broker(kafka)和 consumer 組成。kafka 是乙個分布式的,可劃分的,冗餘備份的永續性的日誌服務。它主要用於處理活躍的流式資料。
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分...
會不會孤單
上班的時候 忽然心裡特別難受 趴在桌子上哭了一會 很長時間了 心裡面一直堵堵的 不痛快 不單純因為失戀 當然 也是因為失戀 一年多的感情 猛的 走到頭了 想起來的時候總覺得一切好象是做夢 隱隱的有什麼事情發生過 卻又不知道到底是什麼 認識他的時候 我還在上學 和所有感情的開始一樣 甜蜜的 難捨難分的...