Categories
程式開發

Kafka權威指南(一):初識Kafka


編者按:本文節選自圖靈程序設計叢書 《Kafka權威指南》一書中的部分章節。

Kafka登場

Kafka 就是為了解決上述問題而設計的一款基於發布與訂閱的消息系統。它一般被稱為“分佈式提交日誌”或者“分佈式流平台”。文件系統或數據庫提交日誌用來提供所有事務的持久記錄,通過重放這些日誌可以重建系統的狀態。同樣地,Kafka 的數據是按照一定順序持久化保存的,可以按需讀取。此外,Kafka 的數據分佈在整個系統裡,具備數據故障保護和性能伸縮能力。

消息和批次

Kafka 的數據單元被稱為 消息。如果你在使用 Kafka 之前已經有數據庫使用經驗,那麼可以把消息看成是數據庫裡的一個“數據行”或一條“記錄”。消息由字節數組組成,所以對於 Kafka 來說,消息裡的數據沒有特別的格式或含義。消息可以有一個可選的元數據,也就是鍵。鍵也是一個字節數組,與消息一樣,對於 Kafka 來說也沒有特殊的含義。當消息以一種可控的方式寫入不同的分區時,會用到鍵。最簡單的例子就是為鍵生成一個一致性散列值,然後使用散列值對主題分區數進行取模,為消息選取分區。這樣可以保證具有相同鍵的消息總是被寫到相同的分區上。第 3 章將詳細介紹鍵的用法。

為了提高效率,消息被分批次寫入 Kafka。批次 就是一組消息,這些消息屬於同一個主題和分區。如果每一個消息都單獨穿行於網絡,會導致大量的網絡開銷,把消息分成批次傳輸可以減少網絡開銷。不過,這要在時間延遲和吞吐量之間作出權衡:批次越大,單位時間內處理的消息就越多,單個消息的傳輸時間就越長。批次數據會被壓縮,這樣可以提升數據的傳輸和存儲能力,但要做更多的計算處理。

模式

對於 Kafka 來說,消息不過是晦澀難懂的字節數組,所以有人建議用一些額外的結構來定義消息內容,讓它們更易於理解。根據應用程序的需求,消息 模式(schema)有許多可用的選項。像 JSON 和 XML 這些簡單的系統,不僅易用,而且可讀性好。不過,它們缺乏強類型處理能力,不同版本之間的兼容性也不是很好。 Kafka 的許多開發者喜歡使用 Apache Avro,它最初是為 Hadoop 開發的一款序列化框架。 Avro 提供了一種緊湊的序列化格式,模式和消息體是分開的,當模式發生變化時,不需要重新生成代碼;它還支持強類型和模式進化,其版本既向前兼容,也向後兼容。

數據格式的一致性對於 Kafka 來說很重要,它消除了消息讀寫操作之間的耦合性。如果讀寫操作緊密地耦合在一起,消息訂閱者需要升級應用程序才能同時處理新舊兩種數據格式。在消息訂閱者升級了之後,消息發布者才能跟著升級,以便使用新的數據格式。新的應用程序如果需要使用數據,就要與消息發布者發生耦合,導致開發者需要做很多繁雜的工作。定義良好的模式,並把它們存放在公共倉庫,可以方便我們理解 Kafka 的消息結構。第 3 章將詳細討論模式和序列化。

主題和分區

Kafka 的消息通過 主題 進行分類。主題就好比數據庫的表,或者文件系統裡的文件夾。主題可以被分為若干個 分區,一個分區就是一個提交日誌。消息以追加的方式寫入分區,然後以先入先出的順序讀取。要注意,由於一個主題一般包含幾個分區,因此無法在整個主題範圍內保證消息的順序,但可以保證消息在單個分區內的順序。圖 1 所示的主題有 4 個分區,消息被追加寫入每個分區的尾部。 Kafka 通過分區來實現數據冗餘和伸縮性。分區可以分佈在不同的服務器上,也就是說,一個主題可以橫跨多個服務器,以此來提供比單個服務器更強大的性能。

Kafka權威指南(一):初識Kafka 1

圖 1:包含多個分區的主題表示

我們通常會使用 這個詞來描述 Kafka 這類系統的數據。很多時候,人們把一個主題的數據看成一個流,不管它有多少個分區。流是一組從生產者移動到消費者的數據。當我們討論流式處理時,一般都是這樣描述消息的。 Kafka Streams、Apache Samza 和 Storm 這些框架以實時的方式處理消息,也就是所謂的流式處理。我們可以將流式處理與離線處理進行比較,比如 Hadoop 就是被設計用於在稍後某個時刻處理大量的數據。第 11 章將會介紹流式處理。

生產者和消費者

Kafka 的客戶端就是 Kafka 系統的用戶,它們被分為兩種基本類型:生產者和消費者。除此之外,還有其他高級客戶端 API——用於數據集成的 Kafka Connect API 和用於流式處理的 Kafka Streams。這些高級客戶端 API 使用生產者和消費者作為內部組件,提供了高級的功能。

生產者 創建消息。在其他發布與訂閱系統中,生產者可能被稱為 發布者寫入者。一般情況下,一個消息會被發佈到一個特定的主題上。生產者在默認情況下把消息均衡地分佈到主題的所有分區上,而並不關心特定消息會被寫到哪個分區。不過,在某些情況下,生產者會把消息直接寫到指定的分區。這通常是通過消息鍵和分區器來實現的,分區器為鍵生成一個散列值,並將其映射到指定的分區上。這樣可以保證包含同一個鍵的消息會被寫到同一個分區上。生產者也可以使用自定義的分區器,根據不同的業務規則將消息映射到分區。第 3 章將詳細介紹生產者。

消費者 讀取消息。在其他發布與訂閱系統中,消費者可能被稱為 訂閱者讀者。消費者訂閱一個或多個主題,並按照消息生成的順序讀取它們。消費者通過檢查消息的偏移量來區分已經讀取過的消息。偏移量 是另一種元數據,它是一個不斷遞增的整數值,在創建消息時,Kafka 會把它添加到消息裡。在給定的分區裡,每個消息的偏移量都是唯一的。消費者把每個分區最後讀取的消息偏移量保存在 Zookeeper 或 Kafka 上,如果消費者關閉或重啟,它的讀取狀態不會丟失。

消費者是 消費者群組 的一部分,也就是說,會有一個或多個消費者共同讀取一個主題。群組保證每個分區只能被一個消費者使用。圖 2 所示的群組中,有 3 個消費者同時讀取一個主題。其中的兩個消費者各自讀取一個分區,另外一個消費者讀取其他兩個分區。消費者與分區之間的映射通常被稱為消費者對分區的 所有權關係

通過這種方式,消費者可以消費包含大量消息的主題。而且,如果一個消費者失效,群組裡的其他消費者可以接管失效消費者的工作。第 4 章將詳細介紹消費者和消費者群組。

Kafka權威指南(一):初識Kafka 2

圖 2:消費者群組從主題讀取消息

broker和集群

一個獨立的 Kafka 服務器被稱為 broker。 broker 接收來自生產者的消息,為消息設置偏移量,並提交消息到磁盤保存。 broker 為消費者提供服務,對讀取分區的請求作出響應,返回已經提交到磁盤上的消息。根據特定的硬件及其性能特徵,單個 broker 可以輕鬆處理數千個分區以及每秒百萬級的消息量。

broker 是 集群 的組成部分。每個集群都有一個 broker 同時充當了 集群控制器 的角色(自動從集群的活躍成員中選舉出來)。控制器負責管理工作,包括將分區分配給 broker 和監控 broker。在集群中,一個分區從屬於一個 broker,該 broker 被稱為分區的 首領。一個分區可以分配給多個 broker,這個時候會發生分區復制(見圖 3)。這種複制機制為分區提供了消息冗餘,如果有一個 broker 失效,其他 broker 可以接管領導權。不過,相關的消費者和生產者都要重新連接到新的首領。第 6 章將詳細介紹集群的操作,包括分區復制。

Kafka權威指南(一):初識Kafka 3

圖 3:集群裡的分區復制

保留消息(在一定期限內)是 Kafka 的一個重要特性。 Kafka broker 默認的消息保留策略是這樣的:要么保留一段時間(比如 7 天),要么保留到消息達到一定大小的字節數(比如 1GB)。當消息數量達到這些上限時,舊消息就會過期並被刪除,所以在任何時刻,可用消息的總量都不會超過配置參數所指定的大小。主題可以配置自己的保留策略,可以將消息保留到不再使用它們為止。例如,用於跟踪用戶活動的數據可能需要保留幾天,而應用程序的度量指標可能只需要保留幾個小時。可以通過配置把主題當作 緊湊型日誌,只有最後一個帶有特定鍵的消息會被保留下來。這種情況對於變更日誌類型的數據來說比較適用,因為人們只關心最後時刻發生的那個變更。

多集群

隨著 Kafka 部署數量的增加,基於以下幾點原因,最好使用多個集群。

  • 數據類型分離
  • 安全需求隔離
  • 多數據中心(災難恢復)

如果使用多個數據中心,就需要在它們之間複製消息。這樣,在線應用程序才可以訪問到多個站點的用戶活動信息。例如,如果一個用戶修改了他們的資料信息,不管從哪個數據中心都應該能看到這些改動。或者多個站點的監控數據可以被聚集到一個部署了分析程序和告警系統的中心位置。不過,Kafka 的消息複製機制只能在單個集群裡進行,不能在多個集群之間進行。

Kafka 提供了一個叫作 MirrorMaker 的工具,可以用它來實現集群間的消息複製。 MirrorMaker 的核心組件包含了一個生產者和一個消費者,兩者之間通過一個隊列相連。

消費者從一個集群讀取消息,生產者把消息發送到另一個集群上。圖 4 展示了一個使用 MirrorMaker 的例子,兩個“本地”集群的消息被聚集到一個“聚合”集群上,然後將該集群複製到其他數據中心。不過,這種方式在創建複雜的數據管道方面顯得有點力不從心。第 7 章將詳細討論這些案例。

Kafka權威指南(一):初識Kafka 4

圖 4:多數據中心架構

圖書簡介https://www.ituring.com.cn/book/2067

Kafka權威指南(一):初識Kafka 5