Kafka 中文文檔 - ApacheCN
https://kafka.apachecn.org/intro.html
Apache Kafka® 是 一個分布式流處理平台. 這到底意味着什么呢?
我們知道流處理平台有以下三種特性:
- 可以讓你發布和訂閱流式的記錄。這一方面與消息隊列或者企業消息系統類似。
- 可以儲存流式的記錄,並且有較好的容錯性。
- 可以在流式記錄產生時就進行處理。
Kafka適合什么樣的場景?
它可以用於兩大類別的應用:
- 構造實時流數據管道,它可以在系統或應用之間可靠地獲取數據。 (相當於message queue)
- 構建實時流式應用程序,對這些流數據進行轉換或者影響。 (就是流處理,通過kafka stream topic和topic之間內部進行變化)
為了理解Kafka是如何做到以上所說的功能,從下面開始,我們將深入探索Kafka的特性。.
首先是一些概念:
- Kafka作為一個集群,運行在一台或者多台服務器上.
- Kafka 通過 topic 對存儲的流數據進行分類。
- 每條記錄中包含一個key,一個value和一個timestamp(時間戳)。
Kafka有四個核心的API:
- The Producer API 允許一個應用程序發布一串流式的數據到一個或者多個Kafka topic。
- The Consumer API 允許一個應用程序訂閱一個或多個 topic ,並且對發布給他們的流式數據進行處理。
- The Streams API 允許一個應用程序作為一個流處理器,消費一個或者多個topic產生的輸入流,然后生產一個輸出流到一個或多個topic中去,在輸入輸出流中進行有效的轉換。
- The Connector API 允許構建並運行可重用的生產者或者消費者,將Kafka topics連接到已存在的應用程序或者數據系統。比如,連接到一個關系型數據庫,捕捉表(table)的所有變更內容。

在Kafka中,客戶端和服務器使用一個簡單、高性能、支持多語言的 TCP 協議.此協議版本化並且向下兼容老版本, 我們為Kafka提供了Java客戶端,也支持許多其他語言的客戶端。
Topics和日志
讓我們首先深入了解下Kafka的核心概念:提供一串流式的記錄— topic 。
Topic 就是數據主題,是數據記錄發布的地方,可以用來區分業務系統。Kafka中的Topics總是多訂閱者模式,一個topic可以擁有一個或者多個消費者來訂閱它的數據。
對於每一個topic, Kafka集群都會維持一個分區日志,如下所示:
每個分區都是有序且順序不可變的記錄集,並且不斷地追加到結構化的commit log文件。分區中的每一個記錄都會分配一個id號來表示順序,我們稱之為offset,offset用來唯一的標識分區中每一條記錄。
Kafka 集群保留所有發布的記錄—無論他們是否已被消費—並通過一個可配置的參數——保留期限來控制. 舉個例子, 如果保留策略設置為2天,一條記錄發布后兩天內,可以隨時被消費,兩天過后這條記錄會被拋棄並釋放磁盤空間。Kafka的性能和數據大小無關,所以長時間存儲數據沒有什么問題.
事實上,在每一個消費者中唯一保存的元數據是offset(偏移量)即消費在log中的位置.偏移量由消費者所控制:通常在讀取記錄后,消費者會以線性的方式增加偏移量,但是實際上,由於這個位置由消費者控制,所以消費者可以采用任何順序來消費記錄。例如,一個消費者可以重置到一個舊的偏移量,從而重新處理過去的數據;也可以跳過最近的記錄,從"現在"開始消費。
這些細節說明Kafka 消費者是非常廉價的—消費者的增加和減少,對集群或者其他消費者沒有多大的影響。比如,你可以使用命令行工具,對一些topic內容執行 tail操作,並不會影響已存在的消費者消費數據。
日志中的 partition(分區)有以下幾個用途。第一,當日志大小超過了單台服務器的限制,允許日志進行擴展。每個單獨的分區都必須受限於主機的文件限制,不過一個主題可能有多個分區,因此可以處理無限量的數據。第二,可以作為並行的單元集—關於這一點,更多細節如下
分布式
日志的分區partition (分布)在Kafka集群的服務器上。每個服務器在處理數據和請求時,共享這些分區。每一個分區都會在已配置的服務器上進行備份,確保容錯性.
每個分區都有一台 server 作為 “leader”,零台或者多台server作為 follwers 。leader server 處理一切對 partition (分區)的讀寫請求,而follwers只需被動的同步leader上的數據。當leader宕機了,followers 中的一台服務器會自動成為新的 leader。每台 server 都會成為某些分區的 leader 和某些分區的 follower,因此集群的負載是平衡的。
生產者
生產者可以將數據發布到所選擇的topic(主題)中。生產者負責將記錄分配到topic的哪一個 partition(分區)中。可以使用循環的方式來簡單地實現負載均衡,也可以根據某些語義分區函數(例如:記錄中的key)來完成。下面會介紹更多關於分區的使用。
消費者
消費者使用一個 消費組 名稱來進行標識,發布到topic中的每條記錄被分配給訂閱消費組中的一個消費者實例.消費者實例可以分布在多個進程中或者多個機器上。
如果所有的消費者實例在同一消費組中,消息記錄會負載平衡到每一個消費者實例.
如果所有的消費者實例在不同的消費組中,每條消息記錄會廣播到所有的消費者進程.
如圖,這個 Kafka 集群有兩台 server 的,四個分區(p0-p3)和兩個消費者組。消費組A有兩個消費者,消費組B有四個消費者。
通常情況下,每個 topic 都會有一些消費組,一個消費組對應一個"邏輯訂閱者"。一個消費組由許多消費者實例組成,便於擴展和容錯。這就是發布和訂閱的概念,只不過訂閱者是一組消費者而不是單個的進程。
在Kafka中實現消費的方式是將日志中的分區划分到每一個消費者實例上,以便在任何時間,每個實例都是分區唯一的消費者。維護消費組中的消費關系由Kafka協議動態處理。如果新的實例加入組,他們將從組中其他成員處接管一些 partition 分區;如果一個實例消失,擁有的分區將被分發到剩余的實例。
Kafka 只保證分區內的記錄是有序的,而不保證主題中不同分區的順序。每個 partition 分區按照key值排序足以滿足大多數應用程序的需求。但如果你需要總記錄在所有記錄的上面,可使用僅有一個分區的主題來實現,這意味着每個消費者組只有一個消費者進程。
保證
high-level Kafka給予以下保證:
- 生產者發送到特定topic partition 的消息將按照發送的順序處理。 也就是說,如果記錄M1和記錄M2由相同的生產者發送,並先發送M1記錄,那么M1的偏移比M2小,並在日志中較早出現
- 一個消費者實例按照日志中的順序查看記錄.
- 對於具有N個副本的主題,我們最多容忍N-1個服務器故障,從而保證不會丟失任何提交到日志中的記錄.
關於保證的更多細節可以看文檔的設計部分。
Kafka作為消息系統
Kafka streams的概念與傳統的企業消息系統相比如何?
傳統的消息系統有兩個模塊: 隊列 和 發布-訂閱。 在隊列中,消費者池從server讀取數據,每條記錄被池子中的一個消費者消費; 在發布訂閱中,記錄被廣播到所有的消費者。兩者均有優缺點。 隊列的優點在於它允許你將處理數據的過程分給多個消費者實例,使你可以擴展處理過程。 不好的是,隊列不是多訂閱者模式的—一旦一個進程讀取了數據,數據就會被丟棄。 而發布-訂閱系統允許你廣播數據到多個進程,但是無法進行擴展處理,因為每條消息都會發送給所有的訂閱者。
消費組在Kafka有兩層概念。在隊列中,消費組允許你將處理過程分發給一系列進程(消費組中的成員)。 在發布訂閱中,Kafka允許你將消息廣播給多個消費組。
Kafka的優勢在於每個topic都有以下特性—可以擴展處理並且允許多訂閱者模式—不需要只選擇其中一個.
Kafka相比於傳統消息隊列還具有更嚴格的順序保證
傳統隊列在服務器上保存有序的記錄,如果多個消費者消費隊列中的數據, 服務器將按照存儲順序輸出記錄。 雖然服務器按順序輸出記錄,但是記錄被異步傳遞給消費者, 因此記錄可能會無序的到達不同的消費者。這意味着在並行消耗的情況下, 記錄的順序是丟失的。因此消息系統通常使用“唯一消費者”的概念,即只讓一個進程從隊列中消費, 但這就意味着不能夠並行地處理數據。
Kafka 設計的更好。topic中的partition是一個並行的概念。 Kafka能夠為一個消費者池提供順序保證和負載平衡,是通過將topic中的partition分配給消費者組中的消費者來實現的, 以便每個分區由消費組中的一個消費者消耗。通過這樣,我們能夠確保消費者是該分區的唯一讀者,並按順序消費數據。 眾多分區保證了多個消費者實例間的負載均衡。但請注意,消費者組中的消費者實例個數不能超過分區的數量。
Kafka 作為存儲系統
許多消息隊列可以發布消息,除了消費消息之外還可以充當中間數據的存儲系統。那么Kafka作為一個優秀的存儲系統有什么不同呢?
數據寫入Kafka后被寫到磁盤,並且進行備份以便容錯。直到完全備份,Kafka才讓生產者認為完成寫入,即使寫入失敗Kafka也會確保繼續寫入
Kafka使用磁盤結構,具有很好的擴展性—50kb和50TB的數據在server上表現一致。
可以存儲大量數據,並且可通過客戶端控制它讀取數據的位置,您可認為Kafka是一種高性能、低延遲、具備日志存儲、備份和傳播功能的分布式文件系統。
關於Kafka提交日志存儲和備份設計的更多細節,可以閱讀 這頁 。
Kafka用做流處理
Kafka 流處理不僅僅用來讀寫和存儲流式數據,它最終的目的是為了能夠進行實時的流處理。
在Kafka中,流處理器不斷地從輸入的topic獲取流數據,處理數據后,再不斷生產流數據到輸出的topic中去。
例如,零售應用程序可能會接收銷售和出貨的輸入流,經過價格調整計算后,再輸出一串流式數據。
簡單的數據處理可以直接用生產者和消費者的API。對於復雜的數據變換,Kafka提供了Streams API。 Stream API 允許應用做一些復雜的處理,比如將流數據聚合或者join。
這一功能有助於解決以下這種應用程序所面臨的問題:處理無序數據,當消費端代碼變更后重新處理輸入,執行有狀態計算等。
Streams API建立在Kafka的核心之上:它使用Producer和Consumer API作為輸入,使用Kafka進行有狀態的存儲, 並在流處理器實例之間使用相同的消費組機制來實現容錯。
批處理
將消息、存儲和流處理結合起來,使得Kafka看上去不一般,但這是它作為流平台所備的.
像HDFS這樣的分布式文件系統可以存儲用於批處理的靜態文件。 一個系統如果可以存儲和處理歷史數據是非常不錯的。
傳統的企業消息系統允許處理訂閱后到達的數據。以這種方式來構建應用程序,並用它來處理即將到達的數據。
Kafka結合了上面所說的兩種特性。作為一個流應用程序平台或者流數據管道,這兩個特性,對於Kafka 來說是至關重要的。
通過組合存儲和低延遲訂閱,流式應用程序可以以同樣的方式處理過去和未來的數據。 一個單一的應用程序可以處理歷史記錄的數據,並且可以持續不斷地處理以后到達的數據,而不是在到達最后一條記錄時結束進程。 這是一個廣泛的流處理概念,其中包含批處理以及消息驅動應用程序
同樣,作為流數據管道,能夠訂閱實時事件使得Kafk具有非常低的延遲; 同時Kafka還具有可靠存儲數據的特性,可用來存儲重要的支付數據, 或者與離線系統進行交互,系統可間歇性地加載數據,也可在停機維護后再次加載數據。流處理功能使得數據可以在到達時轉換數據。
有關Kafka提供的保證、API和功能的更多信息,請看文檔的剩余部分。