提到Kafka很多人的第一印象就是它是一個訊息系統,但Kafka發展至今,它的定位已遠不止於此,而是一個分散式流處理平臺。對於一個流處理平臺通常具有三個關鍵能力:
1. 釋出和訂閱訊息流,在這一點上它與訊息佇列或企業訊息系統類似
2. 以容錯的持久化方式儲存訊息流
3. 在訊息流產生時處理它們
目前,Kafka通常應用於兩大類應用:
1. 構建實時的流資料管道,可靠地在系統和應用程式之間獲取資料
2. 構建實時流的應用程式,對資料流進行轉換或響應
下面我們來一起看一下,Kafka是如何實現以上所說的功能的?首先了解Kafka幾個特性:
-
Kafka作為一個叢集執行在一個或多個伺服器上,這些伺服器可以跨越多個資料中心
-
Kafka叢集儲存的資料流是以topic為類別的
- 每個訊息(也叫記錄record)是由一個key,一個value和一個時間戳構成
Kafka四個核心API
-
Producer API,允許應用程式釋出訊息到1個或多個topic
-
Consumer API,允許應用程式訂閱一個或多個topic,並處理它們訂閱的訊息
-
Streams API,允許應用程式充當一個流處理器,從1個或多個topic消費輸入流,併產生一個輸出流到1個或多個輸出topic,有效地將輸入流轉換到輸出流
- Connector API,允許構建執行可重複使用的生產者或消費者,將topic和現有的應用程式或資料系統連線起來。例如,一個關係型資料庫的聯結器可以捕獲到該庫下每一個表的變化
Client和Server之間的通訊,是通過一條簡單的、高效能支援多語言的TCP協議。並且該協議保持與老版本的相容。Kafka提供了Java客戶端。除了Java 客戶端外,客戶端還支援其他多種語言。
Topic和Log
Topic是釋出的訊息的類別名,可以用來區分來自不同系統的訊息。Kafka中的topic可以有多個訂閱者:即一個topic可以有零個或多個消費者訂閱消費訊息。
對於每一個topic,Kafka叢集維護一個分割槽日誌,如下圖:
每一個分割槽都是一個順序的、不可變的序列資料, 並且不斷的以結構化的提交log方式追加。分割槽中的每條訊息都被分配了稱之為offset的序列號,在每個分割槽中offset是唯一的,通過它可以定位一個分割槽中的唯一一條記錄。 無論訊息是否被消費,Kafka叢集都會持久的儲存所有釋出的訊息,直到過期。Kafka的效能和資料大小無關,所以長時間儲存資料沒有什麼問題。
實際上,每個消費者所持有的僅有的後設資料就是offset,也就是消費者消費在這個log中的位置。這個offset由消費者控制:一般情況下,當消費者消費訊息的時候,offset隨之線性的增加。但是因為實際offset由消費者控制,消費者可以任意指定它的消費位置。同時,一個消費者消費訊息不會影響其他的消費者。
Kafka中採用分割槽的設計主要有兩個目的:第一,當日志大小超過了單臺伺服器的限制,允許日誌進行擴充套件。每個單獨的分割槽都必須受限於主機的檔案限制,不過一個主題可能有多個分割槽,因此可以處理大量的資料。第二,分割槽可以作為並行處理的單元。
分散式
log的分割槽被分佈到叢集中的多個伺服器上。每個伺服器處理它分到的分割槽,根據配置每個分割槽還可以有多個副本作為備份容錯。
每個分割槽有一個leader,零個或多個follower。leader處理此分割槽的所有讀寫請求,而follower被動的同步leader資料。如果leader當機,其它的一個follower會被推舉為新的leader。一臺伺服器可能同時是一個分割槽的leader,另一個分割槽的follower。這樣可以在叢集中進行負載均衡,避免所有的請求都只讓一臺或者某幾臺伺服器處理。
Geo-Replication
Kafka MirrorMaker為叢集提供了geo-replication即異地資料同步技術的支援。藉助MirrorMaker,訊息可以跨多個資料中心或雲區域進行復制。你可以在active/passive場景中用於備份和恢復; 或者在active/active場景中將資料置於更接近使用者的位置,或者支援資料本地化。
生產者
生產者可以採用輪詢、隨機等策略來決定將資料釋出到所選擇的topic中的某個partition上。
消費者
消費者使用一個消費者組名稱來進行標識,釋出到topic中的每條記錄被分配給訂閱消費組中的一個消費者例項,消費者例項可以分佈在多個程式中或者多個機器上。
如果所有的消費者例項在同一個消費者組中,訊息記錄會負載平衡到每一個消費者例項。
如果所有的消費者例項在不同的消費者組中,每條訊息記錄會廣播到所有的消費者程式。
如圖,這個Kafka叢集有兩臺server,四個分割槽和兩個消費者組。消費組A有兩個消費者,消費組B有四個消費者。
通常情況下,每個 topic 都會有一些消費組,一個消費組對應一個"邏輯訂閱者"。一個消費組由許多消費者例項組成,便於擴充套件和容錯。這就是釋出和訂閱的概念,只不過訂閱者是一組消費者而不是單個的程式。
在Kafka中實現消費的方式是將日誌中的分割槽劃分到每一個消費者例項上,以便在任何時間,每個例項都是分割槽唯一的消費者。維護消費者組中的消費關係由Kafka協議動態處理。如果新的例項加入組,他們將從組中其他成員處接管一些分割槽;如果一個例項消失,擁有的分割槽將被分發到剩餘的例項。
Kafka只保證分割槽內的記錄是有序的,而不保證topic中不同分割槽的順序。如果想保證全域性有序,那麼只能有一個分割槽,但是這樣處理的效能會大幅降低。
Kafka的幾個確定性
1. 生產者傳送訊息到特定的topic的分割槽上,訊息將會按照它們傳送的順序依次追加,也就是說,如果一個訊息M1和M2使用相同的producer傳送,M1先傳送,那麼M1將比M2的offset小,並且優先的出現在日誌中
2. 消費者消費的訊息也是按照訊息在日誌中儲存的順序
3. 如果一個topic配置了複製因子為N, 那麼可以允許N-1臺伺服器當機而不丟失任何已經提交的訊息
Kafka作為一個訊息系統
傳統的訊息系統有兩種模式:佇列和釋出-訂閱。在佇列模式中,很多消費者從伺服器讀取訊息並且每個訊息只被其中一個消費者讀取;在釋出-訂閱模式中訊息則被廣播給所有的消費者。這兩種模式都有優缺點,佇列的優點是允許多個消費者瓜分處理資料,這樣可以擴充套件處理。但是,佇列不支援多個訂閱者,一旦消費者讀取該訊息後,該訊息就沒了。而釋出-訂閱允許你廣播資料到多個程式,但是無法進行擴充套件處理,因為每條訊息都會傳送給所有的訂閱者。
Kafka中消費者組有兩個概念:在佇列中消費者組允許同名的消費者組成員瓜分處理;在釋出訂閱中允許你廣播訊息給多個消費者組。
Kafka的優勢在於每個topic都支援擴充套件處理以及允許多訂閱者模式。
Kafka有比傳統的訊息系統更強的順序保證
傳統的訊息系統按順序儲存資料,如果多個消費者從佇列消費,則伺服器按儲存的順序傳送訊息,儘管伺服器按順序傳送,但訊息是非同步傳遞到消費者,因此消費者消費到的訊息可能是無序的。這意味著在並行消費的情況下,順序就無法保證。訊息系統常常通過僅設1個消費者來解決這個問題,但是這意味著無法並行處理資料,效能也就相應降低。
Kafka中的partition就是一個並行處理單元。Kafka通過將topic中的一個partition分配給消費者組中的一個消費者進行消費,保證了消費的順序保證和負載均衡。但是Kafka只能保證一個partition被順序消費,並不能保證全域性有序消費,除非只有一個partition。此外,相同的消費者組中如果有比分割槽數更多的消費者,則多出的消費者會處於空閒狀態,不處理訊息。
Kafka作為一個儲存系統
寫入到Kafka的資料會被寫到磁碟並且備份以保證容錯性,並可以通過應答機制,確保訊息寫入。
Kafka使用的磁碟結構,具有很好的擴充套件性,使得50kb和50TB的資料在伺服器上表現一致。你可以認為kafka是一種高效能、低延遲的提交日誌儲存、備份和傳播功能的分散式檔案系統,並且可以通過客戶端來控制讀取資料的位置。
Kafka的流處理
Kafka流處理不僅僅用來讀寫和儲存流式資料,它最終的目的是為了能夠進行實時的流處理。
在Kafka中,流處理持續獲取輸入topic的資料,進行處理加工,然後寫入輸出topic。例如,一個零售APP,接收銷售和出貨的輸入流,統計數量或調整價格後輸出一系列流資料。
可以直接使用producer和consumer API進行簡單的處理。但是對於複雜的資料轉換,Kafka提供了更強大的streams API,可用於構建聚合計算或join多個流。這一功能有助於解決此類應用面臨的硬性問題:如處理無序的資料,消費者程式碼更改的再處理,執行狀態計算等。
sterams API建立在Kafka的核心之上:使用producer和consumer API作為輸入,利用Kafka做狀態儲存,使用相同的消費者組機制在流處理器例項之間進行容錯保障。
寫在最後
訊息傳遞、儲存和流處理的組合是Kafka作為流式處理平臺的關鍵特性。
像HDFS這樣的分散式檔案系統允許儲存靜態檔案來進行批處理。這樣系統可以有效地儲存和處理歷史資料。而傳統的企業訊息系統允許在你訂閱之後處理將來的資料,並在這些資料到達時處理它。Kafka結合了這兩種能力,這種組合對於Kafka作為流處理應用和流資料管道平臺是至關重要的。
通過訊息儲存和低延遲訂閱,流應用程式可以以同樣的方式處理歷史和將來的資料。一個單一的應用程式可以處理歷史資料,並且可以持續不斷地處理以後到達的資料,而不是在到達最後一條記錄時就結束程式。這是一個廣泛的流處理概念,其中包含批處理以及訊息驅動應用程式。
同樣,作為流資料管道,能夠訂閱實時事件使得Kafk具有非常低的延遲;同時Kafka還具有可靠儲存資料的特性,可用來儲存重要的支付資料或者與離線系統進行互動,系統可間歇性地載入資料,也可在停機維護後再次載入資料。流處理功能使得資料可以在到達時轉換資料。
關注微信公眾號:大資料學習與分享,獲取更對技術乾貨