您的位置:首頁>正文

Kafka詳細的設計和生態系統

更多騰訊海量技術文章, 請關注雲加社區:https://cloud.tencent.com/developer

譯者:Waitingalone

本譯文自Jean-Paul Azar 在 https://dzone.com 發表的 Kafka Detailed Design and Ecosystem , 文中版權, 圖像代碼的資料均歸作者所有。 為了本土化, 翻譯內容略作修改。

Kafka生態系統 - Kafka核心, Kafka流, Kafka連接, Kafka REST代理和模式註冊

Kafka的核心是經紀人, 主題, 日誌, 分區和集群。 核心也包括像MirrorMaker這樣的相關工具。 前面提到的是Kafka, 因為它存在於Apache中。

Kafka生態系統由Kafka Core, Kafka Streams, Kafka Connect, Kafka REST Proxy和Schema Registry組成。 大部分Kafka生態系統的其他部分來自Confluent, 不屬於Apache。

Kafka Stream是Streams API, 用於轉換、匯總和處理來自流的記錄並生成衍生流。 Kafka Connect是API連接器, 用於創建可重用的生產者和消費者(例如, 來自DynamoDB的更改流)。 Kafka REST代理通過REST(HTTP)被用於生產者和消費者。

該架構註冊管理使用模式的AvroKafka的記錄。 Kafka MirrorMaker用於將群集資料複製到另一個群集。

Kafka生態系統:連接源, 連接接收器和Kafka資料流程的示意圖

Kafka連接源是記錄的來源。 Kafka連接水槽是記錄的目的地。

Kafka生態系統:Kafka REST代理和合流模式註冊表

Kafka流 - Kafka流用於流處理

Kafka Stream API基於核心Kafka原語構建, 並擁有自己的生命。 Kafka流可以即時處理流。 Kafka Streams支援流處理器。 流處理器從輸入主題獲取連續的記錄流, 對輸入執行一些處理, 轉換和聚合, 並產生一個或多個輸出流。 例如, 視頻播放機應用程式可能會接收觀看的視頻事件的輸入流, 並暫停視頻, 並輸出使用者偏好流,

然後基於最近的用戶活動或許多用戶的聚合活動來獲取新的視頻推薦, 以查看哪些新的視頻很熱。 Kafka Stream API解決了無序記錄的難題, 跨多個流聚合, 連接來自多個流的資料, 允許有狀態的計算等等。

Kafka生態系統:Kafka流和Kafka連接

Kafka生態系統評論

什麼是Kafka流?

Kafka流可以即時處理流。 它可以聚合多個流, 連接來自多個流的資料, 允許有狀態的計算等等。

什麼是Kafka Connect?

Kafka Connect是連接器API, 用於創建可重用的生產者和消費者(例如, 來自DynamoDB的更改流)。 Kafka連接源是記錄的來源。 Kafka連接水槽是記錄的目的地。

什麼是模式註冊表?

模式註冊管理使用Avro作為Kafka記錄管理模式。

什麼是Kafka鏡子製造商?

Kafka MirrorMaker用於將群集資料複製到另一個群集。

什麼時候可以使用Kafka REST Proxy?

Kafka REST代理通過REST(HTTP)被用於生產者和消費者。 您可以使用它來輕鬆整合現有的代碼庫。

如果您不確定Kafka是什麼, 請參閱什麼是Kafka?

Kafka建築:低級設計

這篇文章從我們關於Kafka架構的系列文章中有所體現, 其中包括Kafka主題架構, Kafka製作者架構, Kafka用戶架構和Kafka生態系統架構。

本文受到Kafka設計部分的啟發。

你可以把它想成懸崖筆記。

Kafka設計的動機

LinkedIn工程師構建Kafka以支持即時分析。 Kafka被設計為提供即時處理流的分析系統。 LinkedIn將Kafka開發為即時處理流式資料饋送的統一平臺。 Kafka背後的目標是構建一個高輸送量的流媒體資料平臺, 支援日誌聚合, 使用者活動等大容量事件流。

為了滿足Kafka的需求擴展, 分散式支援分片和負載均衡。 擴展需求激發了Kafka的分區和消費者模型。 Kafka使用分區, 分散式, 提交日誌來擴展寫入和讀取。 Kafka的分片被稱為分區(Kinesis, 類似於Kafka, 稱為分區“碎片”)。

根據維琪百科的說法, “資料庫分片是資料庫或搜尋引擎中資料的水準分區, 每個分區被稱為分片或資料庫分片, 每個分片被保存在一個單獨的資料庫伺服器實例上, 以傳播負載”。

Kafka被設計為處理來自離線系統的週期性大資料載入以及傳統的消息傳遞用例,低延遲。

MOM是面向消息的中介軟體; 考慮IBM MQSeries,JMS,ActiveMQ和RabbitMQ。像許多MOM一樣,Kafka通過複製和領導選舉來節點故障的容錯。但是,Kafka的設計更像是一個分散式的資料庫事務日誌而不是傳統的消息傳遞系統。與許多MOM不同的是,Kafka的複製是建立在低級設計之上的,並不是事後的想法。

持久性:擁抱檔案系統

Kafka依靠檔案系統來存儲和緩存記錄。

順序寫入硬碟性能的硬碟性能很快(非常快)。JBOD只是一堆磁碟機。帶有6個7200rpm SATA RAID-5陣列的JBOD配置約為600MB /秒。像Cassandra表一樣,Kafka日誌是只寫結構,意思是資料會被附加到日誌的末尾。在使用硬碟驅動器時,順序讀取和寫入速度快,可預測,並且可以通過作業系統進行大量優化。使用HDD時,順序磁片訪問可能比隨機記憶體訪問和SSD更快。

儘管JVM GC的開銷可能會很高,但是Kafka在作業系統上依賴於緩存,這是一個巨大的,快速且穩定的緩存。而且,現代作業系統使用所有可用的主記憶體來進行磁片緩存。作業系統檔緩存幾乎是免費的,沒有作業系統的開銷。實現快取記憶體一致性是正確的挑戰,但是Kafka依靠堅如磐石的作業系統來實現快取記憶體一致性。使用OS進行緩存還會減少緩衝區副本的數量。由於Kafka磁片使用趨向於順序讀取,所以OS預讀緩存令人印象深刻。

Cassandra,Netty和Varnish使用類似的技術。所有這一切都在Kafka檔中得到了很好的解釋,在油漆現場還有一個更有趣的解釋。

大容量硬碟和長時間訪問

Kafka主張長時間循序存取磁片進行讀取和寫入。像Cassandra,LevelDB,RocksDB和其他Kafka使用日誌結構化存儲和壓縮的形式,而不是磁片上可變的BTree。像Cassandra一樣,Kafka使用墓碑而不是立即刪除記錄。

由於磁片這些天有一些無限的空間,並且速度非常快,Kafka可以提供通常在消息系統中不常見的功能,如長時間保持舊消息。這種靈活性允許Kafka有趣的應用。

Kafka生產者負載平衡

生產者向Kafka經紀人詢問有關哪個Kafka經紀人具有哪個主題分區領導的中繼資料,因此不需要路由層。這個領導資料允許生產者直接向Kafka經紀人分區領導發送記錄。

生產者用戶端控制它將消息發佈到哪個分區,並且可以根據某些應用程式邏輯選擇一個分區。生產者可以通過金鑰,迴圈法或使用定制應用程式特定的分區邏輯來分區記錄。

Kafka生產者記錄批量

Kafka生產商支援記錄配料。批量可以通過批量記錄的大小來配置。批次可以根據時間自動刷新。

批量處理對於網路IO輸送量非常有利,並大幅提高輸送量。

緩衝是可配置的,並允許您在更好的輸送量之間進行額外延遲之間的權衡。或者在大量使用的系統的情況下,它可能是更好的平均輸送量,並減少總體延遲。

批量處理允許累積更多的位元組發送,相當於Kafka Brokers上較少的I / O操作,並提高了壓縮效率。為了獲得更高的輸送量,Kafka Producer配置允許基於時間和大小的緩衝。生產者發送多個記錄作為一個批次,而不是逐個發送每個記錄的網路請求。

Kafka生產者配料

Kafka壓縮

在大型流媒體平臺中,瓶頸並不總是CPU或磁片,而是通常網路頻寬。雲中存在更多的網路頻寬問題,如集裝箱化和虛擬化環境,因為多個服務可能共用一個NiC卡。另外,與資料中心或WAN通信時,網路頻寬問題可能會有問題。

批次處理有利於高效壓縮和網路IO輸送量。

Kafka提供了端到端的批量壓縮,而不是一次壓縮記錄,Kafka有效地壓縮了整批記錄。相同的消息批次處理可以一次壓縮並發送到Kafka代理/伺服器,並以壓縮形式寫入日誌分區。您甚至可以配置壓縮,以便在Kafka經紀商將壓縮記錄傳送給使用者之前不進行解壓縮。

Kafka支援GZIP,Snappy和LZ4壓縮協定。

拉與推/流

Kafka消費者從經紀人那裡獲取資料。其他系統經紀商將資料或流資料推送給消費者。消息通常是一個基於拉的系統(SQS,大多數MOM使用拉)。在拉動式的情況下,如果消費者落後,它會在晚些時候趕上。

由於Kafka是基於拉式的,所以它實施了大量的資料分批次處理。Kafka像許多基於拉的系統實現了長期民意調查(SQS,Kafka都這樣做)。長時間輪詢在請求一段時間後保持連接打開並等待回應。

一個基於拉的系統必須拉取資料然後處理它,拉和獲取資料之間總是有一個暫停。

推送資料給消費者(抄寫員,水槽,反應流,RxJava,Akka)。基於推送或資料流系統在處理緩慢或死亡的消費者方面存在問題。當消費率低於生產速度時,推送系統消費者有可能不知所措。一些基於推送的系統使用基於背壓的退避協定,其允許消費者指示其被壓倒看到反應性流。當試圖跟蹤消息確認時,這種不會淹沒消費者和消費者恢復的問題是棘手的。

基於推送或資料流的系統可以立即發送請求,或者累積請求並批量發送(或基於反壓的組合)。基於推送的系統總是在推送資料。消費者可以在處理已經發送的資料的同時累積消息,這有利於減少消息處理的延遲。但是,如果消費者在加工後死亡,那麼經紀人如何知道消費者在哪裡以及何時將資料再次發送給其他消費者。這個問題不是一個容易解決的問題。Kafka通過使用拉式系統來解決這些複雜問題。

傳統的MOM消費者消息狀態跟蹤

對於大多數MOM,經紀人有責任跟蹤哪些消息被標記為已消耗。消息跟蹤不是一件容易的事情。隨著消費者消費資訊,經紀人會跟蹤狀態。

大多數MOM系統的目標是讓經紀人在消費後快速刪除資料。還記得大部分的MOM是在磁片小得多,能力不足,價格昂貴的時候寫的。

這個消息跟蹤比聽起來要複雜(確認功能),因為經紀人必須保持大量狀態來跟蹤每個消息,發送,確認並知道何時刪除或重發消息。

Kafka消費者消息狀態跟蹤

請記住,Kafka主題分為有序分區。每條消息在此有序分區中都有一個偏移量。每個主題分區一次僅由一個消費者組消費。

這種分區佈局的意思是,Broker跟蹤每個消息跟蹤的偏移資料,如MOM,但只需要每個用戶組的偏移量,即存儲的分區偏移對。這種偏移追蹤等同於要追蹤的資料少得多。

消費者定期向Kafka經紀人發送位置資料(消費者組,分區偏移對),經紀人將該偏移資料存儲到偏移主題中。

與MOM相比,抵消風格的消息確認要便宜得多。另外,消費者更加靈活,可以倒退到更早的偏移(重放)。如果有錯誤,那麼修復錯誤,倒回消費者並重播主題。這個倒帶功能是Kafka的一個殺手功能,因為Kafka可以保存很長一段時間的主題日誌資料。

消息傳遞語義

有三種消息傳遞語義:最多一次,至少一次,恰好一次。最多一次的消息可能會丟失,但永遠不會重新發送。至少一次消息是永遠不會丟失的,但可以重新傳遞。每個消息恰好一次只傳送一次。確切地說,曾經是首選的,但更昂貴的,並要求生產者和消費者更多的簿記。

Kafka消費者和消息傳遞語義

回想一下,所有副本具有相同的偏移量的完全相同的日誌分區,並且使用者組在日誌每個主題分區中保持其位置。

為了實現“最多一次”消費者讀取消息,然後將其偏移保存在分區中,並將其發送給代理,最後處理該消息。“最多一次”的問題是消費者可能會在保存其位置之後,但在處理消息之前死亡。然後,接管或重新啟動的消費者將在最後的位置離開,並且不會處理有問題的消息。

為了實現“至少一次”,消費者讀取消息,處理消息,並最終將代價保存到代理。“至少一次”的問題是消費者在處理消息之後但在保存最後偏移位置之前可能崩潰。然後,如果消費者重新啟動或其他消費者接管,消費者可能會收到已處理的消息。“至少一次”是最常見的消息傳遞設置,您的責任是使消息具有冪等性,這意味著兩次獲得相同的消息不會導致問題(兩個借方)。

為了在消費者方面實現“恰好一次”,消費者需要在消費者位置的存儲與消費者的消息處理輸出的存儲之間的兩階段提交。或者,消費者可以將消息處理輸出存儲在與最後偏移相同的位置。

Kafka提供了前兩個,從消費者的角度來看,實現第三個。

Kafka製片人的耐用性和確認

Kafka為耐用性提供了可操作的可預測性語義。發佈消息時,消息被“提交”到日誌,這意味著所有ISR都接受消息。只要至少有一個副本存在,這個提交策略對於耐久性就能很好地工作。

生產者連接可能在發送過程中下降,生產者可能不確定它發送的消息是否經過,然後生產者重新發送消息。這個重發邏輯是為什麼使用消息金鑰和使用冪等消息(重複確定)是重要的。Kafka直到最近(2017年6月)才保證消息不會從生產者重試中複製。

生產者可以重新發送一個消息,直到收到確認,即收到確認。生產者重新發送消息而不知道其發送的其他消息是否與否,從而否定“恰好一次”和“最多一次”的消息傳遞語義。

生產者耐用性

製片人可以指定耐久度級別。製作人可以等待提交的消息。等待提交可確保所有副本都具有該消息的副本。

製片人可以發送沒有確認(0)。生產者可以從分區領導(1)得到一個確認。生產者可以發送並等待來自所有副本(-1)的確認,這是默認的。

改進製片人(2017年6月發行)

Kafka現在支持從生產者“精確地一次”交付,性能改進和分區間的原子寫入。他們通過生產者發送一個序列ID來實現這一點,代理跟蹤生產者是否已經發送了這個序列,如果生產者試圖再次發送它,它會得到重複消息的確認,但是沒有任何東西被保存到日誌中。這種改進不需要API改變。

Kafka製片人原子日誌(2017年6月發行)

Kafka的另一個改進是Kafka生產者在原子筆劃上進行分割。原子寫入意味著Kafka使用者只能看到提交日誌(可配置)。Kafka有一個協調員,寫一個標記到主題日誌,以表示已經成功處理了什麼。事務協調器和事務日誌維護原子寫入的狀態。

原子寫入確實需要一個新的生產者API來處理事務。

這是一個使用新的生產者API的例子。

新的生產者API的交易

producer.initTransaction();try {producer.beginTransaction();producer.send(debitAccountMessage);producer.send(creditOtherAccountMessage);producer.sentOffsetsToTxn(...);producer.commitTransaction();} catch (ProducerFencedTransactionException pfte) {...producer.close();} catch (KafkaException ke) {...producer.abortTransaction();}Kafka複製

Kafka通過可配置數量的Kafka經紀人複製每個主題的分區。Kafka的複製模式是預設的,而不是像大多數MOM那樣的插入功能,因為Kafka從一開始就打算使用分區和多節點。每個主題分區都有一個領導者和零個或多個關注者。

領導者和追隨者被稱為複製品。複製因素是領導者節點加上所有的追隨者。分區領導在Kafka經紀人之間平均分享。消費者只能從領導讀取。製片人只寫信給領導。

追隨者的主題日誌分區與領導者的日誌同步,ISR是領導者的精確副本減去正在進行中的待複製記錄。追隨者像一個普通的Kafka消費者一樣,從他們的領導人那裡批量提取記錄。

Kafka經紀人容錯移轉

Kafka記錄哪些Kafka經紀人還活著。為了活著,Kafka經紀人必須使用ZooKeeper的心跳機制來維護一個ZooKeeper會話,並且必須讓所有的追隨者與領導者同步,而不會落後太多。

這個ZooKeeper會話和同步是被稱為同步的代理生存所需要的。同步副本被稱為ISR。每個領導者都跟蹤一組“同步副本”。

如果ISR /追隨者死亡,則落後,領導者將從ISR中移除追隨者。落後於複製品在 replica.lag.time.max.ms 時段之後不同步的時候 。

當所有ISR將消息應用到其日誌時,消息被認為是“已提交”的。消費者只看到提交的消息。Kafka保證:只要至少有一個ISR,承諾的資訊就不會丟失。

複製的日誌分區

Kafka分區是一個複製的日誌。複製日誌是分散式資料系統原語。複製日誌對於使用狀態機來實現其他分散式系統很有用。一個複製的日誌模型對有序的一系列值“達成一致”。

當一個領導人活著的時候,所有的追隨者只需要複製他們領導的價值觀和秩序。如果領導者死了,Kafka從同步的追隨者中選擇一個新的領導者。如果一個生產者被告知一個消息被提交,然後領導失敗,那麼新當選的領導者必須有這個提交的消息。

你有更多的ISR; 在領導失敗的時候選舉越多。

Kafka和法定人數

法定人數是所需的確認數量,以及必須與選舉領導人進行比較的日誌數量,以確保可用性重疊。大多數系統使用多數票,Kafka不使用簡單的多數投票來提高可用性。

在Kafka,領導人的選擇是基於完整的日誌。如果我們有一個複製因數3,那麼至少兩個ISR必須在領導者聲明發送的消息提交之前同步。如果一個新的領導者需要當選,不超過3次失敗,新的領導者保證有所有承諾的資訊。

在追隨者中,必須至少有一個包含所有提交的消息的副本。大多數投票的問題法定人數是沒有多少失敗,有一個無法操作的群集。

Kafka法定人數多數的情監偵

Kafka為每個領導人維護一套情監偵。只有這一套ISR的成員才有資格領導選舉。在所有ISR確認寫入之前,生產者寫入分區的內容不會被提交。只要ISR設置發生變化,ISR就會持續到ZooKeeper。只有屬於ISR成員的副本才有資格當選領導。

ISR法定人數的這種風格允許生產者在沒有大多數所有節點的情況下繼續工作,但只有ISR多數票。ISR仲裁的這種風格也允許副本重新加入ISR集並且擁有其投票計數,但是在加入之前必須完全重新同步,即使副本在其崩潰期間丟失未刷新的資料也是如此。

所有節點同時死亡。怎麼辦?

Kafka關於資料丟失的保證只有在至少一個副本同步的情況下才有效。

如果所有正在複製分區領導者的追隨者都立即死亡,那麼資料丟失Kafka保證是無效的。如果分區的所有副本都關閉,則預設情況下,Kafka選擇作為首領活動的第一個副本(不一定在ISR集合中)(config unclean.leader.election.enable = true是缺省值)。這種選擇有利於可用性的一致性。

如果一致性比您的用例的可用性更重要,那麼您可以設置配置, unclean.leader.election.enable=false 那麼如果所有副本都停止運行一個分區,Kafka會等待第一個ISR成員(而不是第一個副本)活躍起來以選出新的領導者。

生產者選擇耐久性

生產者可以通過設置acks(0),僅前導(1)或所有副本(-1)來選擇耐久性。

acks = all是預設值。總而言之,當所有當前的同步複製品(ISR)都收到該消息時,便會發生這種情況。

您可以在一致性和可用性之間進行權衡。如果耐用性超過可用性,那麼禁用不乾淨的領導者選舉並指定最小的ISR大小。

最小的ISR規模越大,保證一致性就越好。但是,如果ISR集的大小小於最小閾值,則ISR的最小ISR越高,可用性就越低,因為分區不可用。

配額

Kafka已經為消費者和生產者制定了限制他們被允許消費的頻寬的限額。這些配額阻止消費者或生產者佔用Kafka經紀人資源。配額是由用戶端ID或用戶。配額資料存儲在ZooKeeper中,所以更改不需要重新開機Kafka代理。

Kafka低級設計和體系結構回顧

你如何防止從一個寫作不好的消費者的拒絕服務攻擊?

使用配額限制消費者的頻寬。

什麼是默認的生產者耐用性(acks)水準?

所有。這意味著所有ISR必須將消息寫入其日誌分區。

如果所有的Kafka節點都一次下來,預設情況下會發生什麼?

Kafka選擇第一個複製品(不一定在ISR集合中),作為領導者活躍起來, unclean.leader.election.enable=true 以支援可用性。

為什麼Kafka記錄批量重要?

通過線路以及磁片優化IO輸送量。它還通過壓縮整個批次來提高壓縮效率。

Kafka的一些設計目標是什麼?

成為高輸送量,可擴展的流媒體資料平臺,用於對日誌聚合,使用者活動等大容量事件流進行即時分析。

截至2017年6月,Kafka中有哪些新功能?

生產者原子寫入,性能改進和生產者不發送重複的消息。

什麼是不同的消息傳遞語義?

有三種消息傳遞語義:最多一次,至少一次,恰好一次。

原文連結:https://dzone.com/articles/kafka-detailed-design-and-ecosystem

原文作者:Jean-Paul Azar

Kafka被設計為處理來自離線系統的週期性大資料載入以及傳統的消息傳遞用例,低延遲。

MOM是面向消息的中介軟體; 考慮IBM MQSeries,JMS,ActiveMQ和RabbitMQ。像許多MOM一樣,Kafka通過複製和領導選舉來節點故障的容錯。但是,Kafka的設計更像是一個分散式的資料庫事務日誌而不是傳統的消息傳遞系統。與許多MOM不同的是,Kafka的複製是建立在低級設計之上的,並不是事後的想法。

持久性:擁抱檔案系統

Kafka依靠檔案系統來存儲和緩存記錄。

順序寫入硬碟性能的硬碟性能很快(非常快)。JBOD只是一堆磁碟機。帶有6個7200rpm SATA RAID-5陣列的JBOD配置約為600MB /秒。像Cassandra表一樣,Kafka日誌是只寫結構,意思是資料會被附加到日誌的末尾。在使用硬碟驅動器時,順序讀取和寫入速度快,可預測,並且可以通過作業系統進行大量優化。使用HDD時,順序磁片訪問可能比隨機記憶體訪問和SSD更快。

儘管JVM GC的開銷可能會很高,但是Kafka在作業系統上依賴於緩存,這是一個巨大的,快速且穩定的緩存。而且,現代作業系統使用所有可用的主記憶體來進行磁片緩存。作業系統檔緩存幾乎是免費的,沒有作業系統的開銷。實現快取記憶體一致性是正確的挑戰,但是Kafka依靠堅如磐石的作業系統來實現快取記憶體一致性。使用OS進行緩存還會減少緩衝區副本的數量。由於Kafka磁片使用趨向於順序讀取,所以OS預讀緩存令人印象深刻。

Cassandra,Netty和Varnish使用類似的技術。所有這一切都在Kafka檔中得到了很好的解釋,在油漆現場還有一個更有趣的解釋。

大容量硬碟和長時間訪問

Kafka主張長時間循序存取磁片進行讀取和寫入。像Cassandra,LevelDB,RocksDB和其他Kafka使用日誌結構化存儲和壓縮的形式,而不是磁片上可變的BTree。像Cassandra一樣,Kafka使用墓碑而不是立即刪除記錄。

由於磁片這些天有一些無限的空間,並且速度非常快,Kafka可以提供通常在消息系統中不常見的功能,如長時間保持舊消息。這種靈活性允許Kafka有趣的應用。

Kafka生產者負載平衡

生產者向Kafka經紀人詢問有關哪個Kafka經紀人具有哪個主題分區領導的中繼資料,因此不需要路由層。這個領導資料允許生產者直接向Kafka經紀人分區領導發送記錄。

生產者用戶端控制它將消息發佈到哪個分區,並且可以根據某些應用程式邏輯選擇一個分區。生產者可以通過金鑰,迴圈法或使用定制應用程式特定的分區邏輯來分區記錄。

Kafka生產者記錄批量

Kafka生產商支援記錄配料。批量可以通過批量記錄的大小來配置。批次可以根據時間自動刷新。

批量處理對於網路IO輸送量非常有利,並大幅提高輸送量。

緩衝是可配置的,並允許您在更好的輸送量之間進行額外延遲之間的權衡。或者在大量使用的系統的情況下,它可能是更好的平均輸送量,並減少總體延遲。

批量處理允許累積更多的位元組發送,相當於Kafka Brokers上較少的I / O操作,並提高了壓縮效率。為了獲得更高的輸送量,Kafka Producer配置允許基於時間和大小的緩衝。生產者發送多個記錄作為一個批次,而不是逐個發送每個記錄的網路請求。

Kafka生產者配料

Kafka壓縮

在大型流媒體平臺中,瓶頸並不總是CPU或磁片,而是通常網路頻寬。雲中存在更多的網路頻寬問題,如集裝箱化和虛擬化環境,因為多個服務可能共用一個NiC卡。另外,與資料中心或WAN通信時,網路頻寬問題可能會有問題。

批次處理有利於高效壓縮和網路IO輸送量。

Kafka提供了端到端的批量壓縮,而不是一次壓縮記錄,Kafka有效地壓縮了整批記錄。相同的消息批次處理可以一次壓縮並發送到Kafka代理/伺服器,並以壓縮形式寫入日誌分區。您甚至可以配置壓縮,以便在Kafka經紀商將壓縮記錄傳送給使用者之前不進行解壓縮。

Kafka支援GZIP,Snappy和LZ4壓縮協定。

拉與推/流

Kafka消費者從經紀人那裡獲取資料。其他系統經紀商將資料或流資料推送給消費者。消息通常是一個基於拉的系統(SQS,大多數MOM使用拉)。在拉動式的情況下,如果消費者落後,它會在晚些時候趕上。

由於Kafka是基於拉式的,所以它實施了大量的資料分批次處理。Kafka像許多基於拉的系統實現了長期民意調查(SQS,Kafka都這樣做)。長時間輪詢在請求一段時間後保持連接打開並等待回應。

一個基於拉的系統必須拉取資料然後處理它,拉和獲取資料之間總是有一個暫停。

推送資料給消費者(抄寫員,水槽,反應流,RxJava,Akka)。基於推送或資料流系統在處理緩慢或死亡的消費者方面存在問題。當消費率低於生產速度時,推送系統消費者有可能不知所措。一些基於推送的系統使用基於背壓的退避協定,其允許消費者指示其被壓倒看到反應性流。當試圖跟蹤消息確認時,這種不會淹沒消費者和消費者恢復的問題是棘手的。

基於推送或資料流的系統可以立即發送請求,或者累積請求並批量發送(或基於反壓的組合)。基於推送的系統總是在推送資料。消費者可以在處理已經發送的資料的同時累積消息,這有利於減少消息處理的延遲。但是,如果消費者在加工後死亡,那麼經紀人如何知道消費者在哪裡以及何時將資料再次發送給其他消費者。這個問題不是一個容易解決的問題。Kafka通過使用拉式系統來解決這些複雜問題。

傳統的MOM消費者消息狀態跟蹤

對於大多數MOM,經紀人有責任跟蹤哪些消息被標記為已消耗。消息跟蹤不是一件容易的事情。隨著消費者消費資訊,經紀人會跟蹤狀態。

大多數MOM系統的目標是讓經紀人在消費後快速刪除資料。還記得大部分的MOM是在磁片小得多,能力不足,價格昂貴的時候寫的。

這個消息跟蹤比聽起來要複雜(確認功能),因為經紀人必須保持大量狀態來跟蹤每個消息,發送,確認並知道何時刪除或重發消息。

Kafka消費者消息狀態跟蹤

請記住,Kafka主題分為有序分區。每條消息在此有序分區中都有一個偏移量。每個主題分區一次僅由一個消費者組消費。

這種分區佈局的意思是,Broker跟蹤每個消息跟蹤的偏移資料,如MOM,但只需要每個用戶組的偏移量,即存儲的分區偏移對。這種偏移追蹤等同於要追蹤的資料少得多。

消費者定期向Kafka經紀人發送位置資料(消費者組,分區偏移對),經紀人將該偏移資料存儲到偏移主題中。

與MOM相比,抵消風格的消息確認要便宜得多。另外,消費者更加靈活,可以倒退到更早的偏移(重放)。如果有錯誤,那麼修復錯誤,倒回消費者並重播主題。這個倒帶功能是Kafka的一個殺手功能,因為Kafka可以保存很長一段時間的主題日誌資料。

消息傳遞語義

有三種消息傳遞語義:最多一次,至少一次,恰好一次。最多一次的消息可能會丟失,但永遠不會重新發送。至少一次消息是永遠不會丟失的,但可以重新傳遞。每個消息恰好一次只傳送一次。確切地說,曾經是首選的,但更昂貴的,並要求生產者和消費者更多的簿記。

Kafka消費者和消息傳遞語義

回想一下,所有副本具有相同的偏移量的完全相同的日誌分區,並且使用者組在日誌每個主題分區中保持其位置。

為了實現“最多一次”消費者讀取消息,然後將其偏移保存在分區中,並將其發送給代理,最後處理該消息。“最多一次”的問題是消費者可能會在保存其位置之後,但在處理消息之前死亡。然後,接管或重新啟動的消費者將在最後的位置離開,並且不會處理有問題的消息。

為了實現“至少一次”,消費者讀取消息,處理消息,並最終將代價保存到代理。“至少一次”的問題是消費者在處理消息之後但在保存最後偏移位置之前可能崩潰。然後,如果消費者重新啟動或其他消費者接管,消費者可能會收到已處理的消息。“至少一次”是最常見的消息傳遞設置,您的責任是使消息具有冪等性,這意味著兩次獲得相同的消息不會導致問題(兩個借方)。

為了在消費者方面實現“恰好一次”,消費者需要在消費者位置的存儲與消費者的消息處理輸出的存儲之間的兩階段提交。或者,消費者可以將消息處理輸出存儲在與最後偏移相同的位置。

Kafka提供了前兩個,從消費者的角度來看,實現第三個。

Kafka製片人的耐用性和確認

Kafka為耐用性提供了可操作的可預測性語義。發佈消息時,消息被“提交”到日誌,這意味著所有ISR都接受消息。只要至少有一個副本存在,這個提交策略對於耐久性就能很好地工作。

生產者連接可能在發送過程中下降,生產者可能不確定它發送的消息是否經過,然後生產者重新發送消息。這個重發邏輯是為什麼使用消息金鑰和使用冪等消息(重複確定)是重要的。Kafka直到最近(2017年6月)才保證消息不會從生產者重試中複製。

生產者可以重新發送一個消息,直到收到確認,即收到確認。生產者重新發送消息而不知道其發送的其他消息是否與否,從而否定“恰好一次”和“最多一次”的消息傳遞語義。

生產者耐用性

製片人可以指定耐久度級別。製作人可以等待提交的消息。等待提交可確保所有副本都具有該消息的副本。

製片人可以發送沒有確認(0)。生產者可以從分區領導(1)得到一個確認。生產者可以發送並等待來自所有副本(-1)的確認,這是默認的。

改進製片人(2017年6月發行)

Kafka現在支持從生產者“精確地一次”交付,性能改進和分區間的原子寫入。他們通過生產者發送一個序列ID來實現這一點,代理跟蹤生產者是否已經發送了這個序列,如果生產者試圖再次發送它,它會得到重複消息的確認,但是沒有任何東西被保存到日誌中。這種改進不需要API改變。

Kafka製片人原子日誌(2017年6月發行)

Kafka的另一個改進是Kafka生產者在原子筆劃上進行分割。原子寫入意味著Kafka使用者只能看到提交日誌(可配置)。Kafka有一個協調員,寫一個標記到主題日誌,以表示已經成功處理了什麼。事務協調器和事務日誌維護原子寫入的狀態。

原子寫入確實需要一個新的生產者API來處理事務。

這是一個使用新的生產者API的例子。

新的生產者API的交易

producer.initTransaction();try {producer.beginTransaction();producer.send(debitAccountMessage);producer.send(creditOtherAccountMessage);producer.sentOffsetsToTxn(...);producer.commitTransaction();} catch (ProducerFencedTransactionException pfte) {...producer.close();} catch (KafkaException ke) {...producer.abortTransaction();}Kafka複製

Kafka通過可配置數量的Kafka經紀人複製每個主題的分區。Kafka的複製模式是預設的,而不是像大多數MOM那樣的插入功能,因為Kafka從一開始就打算使用分區和多節點。每個主題分區都有一個領導者和零個或多個關注者。

領導者和追隨者被稱為複製品。複製因素是領導者節點加上所有的追隨者。分區領導在Kafka經紀人之間平均分享。消費者只能從領導讀取。製片人只寫信給領導。

追隨者的主題日誌分區與領導者的日誌同步,ISR是領導者的精確副本減去正在進行中的待複製記錄。追隨者像一個普通的Kafka消費者一樣,從他們的領導人那裡批量提取記錄。

Kafka經紀人容錯移轉

Kafka記錄哪些Kafka經紀人還活著。為了活著,Kafka經紀人必須使用ZooKeeper的心跳機制來維護一個ZooKeeper會話,並且必須讓所有的追隨者與領導者同步,而不會落後太多。

這個ZooKeeper會話和同步是被稱為同步的代理生存所需要的。同步副本被稱為ISR。每個領導者都跟蹤一組“同步副本”。

如果ISR /追隨者死亡,則落後,領導者將從ISR中移除追隨者。落後於複製品在 replica.lag.time.max.ms 時段之後不同步的時候 。

當所有ISR將消息應用到其日誌時,消息被認為是“已提交”的。消費者只看到提交的消息。Kafka保證:只要至少有一個ISR,承諾的資訊就不會丟失。

複製的日誌分區

Kafka分區是一個複製的日誌。複製日誌是分散式資料系統原語。複製日誌對於使用狀態機來實現其他分散式系統很有用。一個複製的日誌模型對有序的一系列值“達成一致”。

當一個領導人活著的時候,所有的追隨者只需要複製他們領導的價值觀和秩序。如果領導者死了,Kafka從同步的追隨者中選擇一個新的領導者。如果一個生產者被告知一個消息被提交,然後領導失敗,那麼新當選的領導者必須有這個提交的消息。

你有更多的ISR; 在領導失敗的時候選舉越多。

Kafka和法定人數

法定人數是所需的確認數量,以及必須與選舉領導人進行比較的日誌數量,以確保可用性重疊。大多數系統使用多數票,Kafka不使用簡單的多數投票來提高可用性。

在Kafka,領導人的選擇是基於完整的日誌。如果我們有一個複製因數3,那麼至少兩個ISR必須在領導者聲明發送的消息提交之前同步。如果一個新的領導者需要當選,不超過3次失敗,新的領導者保證有所有承諾的資訊。

在追隨者中,必須至少有一個包含所有提交的消息的副本。大多數投票的問題法定人數是沒有多少失敗,有一個無法操作的群集。

Kafka法定人數多數的情監偵

Kafka為每個領導人維護一套情監偵。只有這一套ISR的成員才有資格領導選舉。在所有ISR確認寫入之前,生產者寫入分區的內容不會被提交。只要ISR設置發生變化,ISR就會持續到ZooKeeper。只有屬於ISR成員的副本才有資格當選領導。

ISR法定人數的這種風格允許生產者在沒有大多數所有節點的情況下繼續工作,但只有ISR多數票。ISR仲裁的這種風格也允許副本重新加入ISR集並且擁有其投票計數,但是在加入之前必須完全重新同步,即使副本在其崩潰期間丟失未刷新的資料也是如此。

所有節點同時死亡。怎麼辦?

Kafka關於資料丟失的保證只有在至少一個副本同步的情況下才有效。

如果所有正在複製分區領導者的追隨者都立即死亡,那麼資料丟失Kafka保證是無效的。如果分區的所有副本都關閉,則預設情況下,Kafka選擇作為首領活動的第一個副本(不一定在ISR集合中)(config unclean.leader.election.enable = true是缺省值)。這種選擇有利於可用性的一致性。

如果一致性比您的用例的可用性更重要,那麼您可以設置配置, unclean.leader.election.enable=false 那麼如果所有副本都停止運行一個分區,Kafka會等待第一個ISR成員(而不是第一個副本)活躍起來以選出新的領導者。

生產者選擇耐久性

生產者可以通過設置acks(0),僅前導(1)或所有副本(-1)來選擇耐久性。

acks = all是預設值。總而言之,當所有當前的同步複製品(ISR)都收到該消息時,便會發生這種情況。

您可以在一致性和可用性之間進行權衡。如果耐用性超過可用性,那麼禁用不乾淨的領導者選舉並指定最小的ISR大小。

最小的ISR規模越大,保證一致性就越好。但是,如果ISR集的大小小於最小閾值,則ISR的最小ISR越高,可用性就越低,因為分區不可用。

配額

Kafka已經為消費者和生產者制定了限制他們被允許消費的頻寬的限額。這些配額阻止消費者或生產者佔用Kafka經紀人資源。配額是由用戶端ID或用戶。配額資料存儲在ZooKeeper中,所以更改不需要重新開機Kafka代理。

Kafka低級設計和體系結構回顧

你如何防止從一個寫作不好的消費者的拒絕服務攻擊?

使用配額限制消費者的頻寬。

什麼是默認的生產者耐用性(acks)水準?

所有。這意味著所有ISR必須將消息寫入其日誌分區。

如果所有的Kafka節點都一次下來,預設情況下會發生什麼?

Kafka選擇第一個複製品(不一定在ISR集合中),作為領導者活躍起來, unclean.leader.election.enable=true 以支援可用性。

為什麼Kafka記錄批量重要?

通過線路以及磁片優化IO輸送量。它還通過壓縮整個批次來提高壓縮效率。

Kafka的一些設計目標是什麼?

成為高輸送量,可擴展的流媒體資料平臺,用於對日誌聚合,使用者活動等大容量事件流進行即時分析。

截至2017年6月,Kafka中有哪些新功能?

生產者原子寫入,性能改進和生產者不發送重複的消息。

什麼是不同的消息傳遞語義?

有三種消息傳遞語義:最多一次,至少一次,恰好一次。

原文連結:https://dzone.com/articles/kafka-detailed-design-and-ecosystem

原文作者:Jean-Paul Azar

同類文章
Next Article
喜欢就按个赞吧!!!
点击关闭提示