Kafka流處理內幕詳解

哥不是小蘿莉發表於2021-07-31

1.概述

流處理是一種用來處理無窮資料集的資料處理引擎。通常無窮資料集具有以下幾個特點:

  • 無窮資料:持續產生的資料,它們通常會被稱為流資料。例如:銀行信用卡交易訂單、股票交易就、遊戲角色移動產生的資料等;
  • 低延時:流資料通常都是實時處理,資料實時產生,然後流處理引擎實時處理流資料,因此延時很短。

2.內容

2.1 什麼是流處理

對於儲存在Kafka系統內的資料,Kafka系統提供了一種進行處理和分析的功能——流處理,它具有以下特性。

1. 是一個輕量級的類庫

Kafka流處理提供了一個非常輕量級的Java類庫,它能夠輕而易舉地整合到任意的Java應用程式中,打包和部署的方式也沒有特殊的要求。

2. 擁有良好的可擴充套件性和容錯性

Kafka流處理除了依賴Kafka系統外,對外界不存在任何依賴。在系統達到瓶頸時,Kafka流處理可以使用Kafka系統的分割槽機制,輕鬆地實現水平擴充套件來解決瓶頸問題。同時,通過記錄狀態(視窗操作、聚合操作等)來實現高效的操作。

3. 擁有豐富的應用介面

Kafka流處理對底層的應用介面進行了封裝,同時,對拓撲結構進行了高度抽象。

4. 具有靈活的彈性伸縮功能

在只讀取資料一次的情況下,流處理應用程式無需使用者介入,也能自動修改引數,實現應用程式的自動擴容和減容。

2.2 什麼是流式計算

通常情況下,流式計算與批處理計算會放在一起做比較分析。
(1)在流式計算模型中,資料的輸入是持續不斷的,這意味著永遠不知道資料的上限是多少,因此,計算產生的結果也是持續輸出的,流程如下圖所示。流式計算一般對實時性要求較高,為了提升計算效率,通常會採用增量計算來替代全量計算。

 

(2)在批處理計算模型中,通常資料上限是可知的,一般會先定義計算邏輯,然後進行全量計算,並將計算結果一次性輸出。流程如下圖所示。

 

 

2.3 為何需要流處理

在大資料生態圈中存在很多流處理系統或框架,下面介紹三個非常流行的開源流處理框架。

  • Flink:一個對流資料和批次資料進行分散式處理的框架,它主要由Java程式碼實現。對於Flink而言,處理的主要是流資料,批次資料只是流資料的一個特例而已。當前Flink支援SQL語法來操作流資料。
  • Spark Streaming:一種構建在Spark上的實時計算框架,用來處理流資料。Spark功能強大,同樣支援SQL語法來操作流資料。
  • Storm:一個用於事件流的分散式處理框架,主要由Clojure實現。該框架的目標是將輸入流、處理、以及輸出模組結合在一起,並組建成一套有向無環圖。當前Storm也支援SQL語法來操作流資料。

既然已存在這些優秀的實時處理框架,為何Kafka還需要設計流處理呢?原因有以下幾點:

1. 簡單易用

Flink、Spark、Storm都屬於流式處理框架,而Kafka流處理是基於Kafka系統的流處理類庫,並非框架。
通常情況下,框架有固定的執行方式,使用者需要了解框架的執行流程,這使得學習成本增加。而Kafka流處理作為一個類庫,使用者可以直接呼叫具體的類,整個執行邏輯都在使用者的掌控之中,不會產生額外的學習成本。

2. 方便部署

Kafka流處理作為一個類庫,可以非常方便地整合到應用程式中,並且對應用程式的打包和部署沒有任何限制。

3. 資源使用率低

流式處理框架在啟動例項時會預分配系統資源,即使是應用程式例項,框架自身也需要佔用一部分系統資源。例如,一個Spark Streaming應用程式需要給Shuffle和Storage事先申請記憶體。
使用Kafka流處理不涉及框架例項的執行,所以不會額外佔用系統資源。

提示:
Shuffle可以理解為一個溝通資料連線的橋樑。
Storage負責把資料儲存到記憶體、磁碟或者堆外記憶體,有時還需要在其他節點建立副本來儲存。

3.瞭解流處理架構

Kafka流處理使用Kafka系統的消費者類庫和生產者類庫來構建應用程式,並利用Kafka系統自身的特性來提供資料並行性、分散式協調性、容錯性、易操作性等,從而簡化使用者開發應用程式的步驟。具體工作流程如下圖所示:

 

 

 Kafka流處理輸入的資料來源於Kafka系統中的業務主題,處理後的結果會儲存到Kafka系統中新的業務主題中。 上圖中,消費者程式和生產者程式並不需要使用者在應用程式中顯式地例項化,而是通過Kafka流處理根據引數來隱式地例項化和管理,這讓操作變得更加簡單。使用者只需關心核心業務邏輯(即上圖中的任務模組)的編寫,其他的都交由Kafka流處理來實現。

3.1 流分割槽與任務

Kafka流處理通過流分割槽來處理資料,內容包含儲存和傳輸資料。Kafka流處理使用分割槽和任務概念來作為併發模型中的邏輯單元。在併發環境中,通過分割槽資料來保證靈活性、可擴充套件性、高效性和容錯性。

1. 流分割槽的作用

在Kafka流處理中,每個流分割槽是完全而有序的資料佇列。這些有序資料記錄會對映到Kafka系統主題分割槽中。
流資料中對映的訊息資料來自於Kafka系統主題。訊息資料中鍵(Key)值是Kafka和Kafka流處理的關鍵,它決定了資料如何被路由到指定分割槽。

2. 任務的作用

一個應用程式可以被拆分成多個任務來執行。Kafka流處理會根據輸入流分割槽來建立固定數量的任務,每個任務分配一個輸入流分割槽列表。
任務是應用程式並行執行時的固定單元,因此分割槽對任務的分配不會造成影響。任務可以基於分配到的分割槽來實現相關處理流程,同時為每個分配到的分割槽保留一個緩衝區,並從這些緩衝區逐一地處理訊息,這樣可以讓Kafka流處理的任務自動並行處理。

提示:
在一個子處理流程中,如果一個Kafka流處理應用程式指定了多個處理流程,則每個任務只例項化一個處理物件。
另外,一個處理流程可以被拆分為多個獨立的子處理流程,只要保證子處理流程與其他子處理流程沒有交集即可。通過這種方式可以讓任務之間保持負載均衡。

 

 

Kafka流處理不是一個資源管理器,而是一個類庫。 Kafka流處理可以執行在任何流處理應用程式中。應用程式的多個例項可以執行在同一臺主機上,也可以分發到不同的主機進行執行。如果一個應用程式例項發生異常導致不可用,則該任務將會自動地在其他的例項上重新建立,並從相同的分割槽中繼續讀取資料。

3.2 執行緒模型

Kafka流處理允許使用者配置多個執行緒,並通過多執行緒來均衡應用程式中的任務數。每個執行緒的處理流程可以執行一個或者多個任務。

1. 執行緒模型的處理流程

下圖所示是使用一個執行緒來處理多個流任務。

 

 

 

啟動多個流執行緒或更多的應用程式,只需要複製執行流程即可。比如,將一份業務邏輯處理程式碼複製到不同的主機上進行執行。這樣做的好處是,通過多執行緒來並行處理不同Kafka系統主題分割槽中的資料,能提升處理效率。這些執行緒之間的狀態是不共享的。因此,不需要執行緒間的協作。這使得執行一個多併發的處理流程例項變得非常簡單。

2. 執行緒模型的優點

  • 易擴充套件:對Kafka流處理應用程式進行擴充套件是很容易的,只需要執行應用程式的例項即可。
  • 自動分配分割槽:Kafka流處理會監聽任務數量的變化,並自動給任務分配分割槽。
  • 多執行緒:使用者在啟動應用程式時,可以根據Kafka系統輸入主題中的分割槽數來設定執行緒數。每個執行緒至少對應一個分割槽。

 

3. 多執行緒併發場景

假設有一個Kafka流處理應用程式,它從兩個業務主題(A和B)中讀取資料,每個業務主題都有3個分割槽。當使用者在一臺主機上啟動一個應用程式例項,並設定執行緒數為2,最終會出現兩個Kafka流處理執行緒。
由於輸入主題A和輸入主題B的最大分割槽數均為3,所以Kafka流處理會預設將其拆分為3個任務,然後將合計的6個分割槽(主題A和主題B的分割槽總和)均勻地分佈到3個任務中。
這種情況下,每個任務會同時從兩個分割槽中讀取資料。最終,這3個任務會被均勻地分佈在兩個執行緒當中。兩個執行緒的作用分別如下。
執行緒1包含兩個任務,從四個分割槽(主題A的兩個分割槽和主題B的兩個分割槽)中讀取資料;
執行緒2包含一個任務,從兩個分割槽(主題A的一個分割槽和主題B的一個分割槽)中讀取資料。

隨著業務資料量的增加,需要對現有的應用程式進行擴充。實施的具體方案是,在另外一臺主機上啟動該應用程式,並設定執行緒數為1。具體實現流程如下圖所示。

 

 

當前總分割槽數為6個,執行緒總數為3個。當任務被重新分配時,相同的分割槽、任務和儲存狀態,都會被移到新的執行緒,從而使應用程式達到負載均衡。

3.3 本地狀態儲存

 

Kafka流處理提供的狀態儲存機制,可用來儲存和查詢應用程式產生的狀態資料。例如,在執行連線、聚合操作時,Kafka流處理會自動建立和管理這些狀態儲存。
下圖展示了兩個流處理任務,以及它們專用的本地狀態儲存。
在Kafka流處理應用程式中,每個流任務可以整合一個或多個本地狀態儲存,這些本地狀態儲存可以通過應用介面來進行儲存和查詢。同時,Kafka流處理也為本地狀態儲存提供了容錯機制和自動恢復功能。

 

 

 3.4 容錯性

Kafka流處理繼承了Kafka系統主題分割槽的兩大能力——高可用能力、副本故障自動轉移能力。因而,在流資料持久化到Kafka系統主題時,即使應用程式失敗也會自動重新處理。
Kafka流處理中的任務利用Kafka系統客戶端提供的容錯機制來處理異常問題。如果某個任務在發生故障的主機上執行,則Kafka流處理會自動在應用程式的其他執行例項中重新啟動該任務。
每個狀態儲存都會維護一個更改日誌主題的副本,用來跟蹤狀態的更新。這些更改日誌主題也進行了分割槽,以便每個本地狀態儲存例項和訪問儲存的任務都有其專屬的更改日誌主題分割槽。在更該日誌主題上啟用日誌壓縮,可以方便、安全地清理無用資料,避免主題資料無限增長。
如果任務在一臺主機上執行失敗,之後在另一臺主機重新啟動,則Kafka流處理在恢復對新啟動的任務之前,通過回滾機制將關聯的狀態儲存恢復到故障之前,整個過程對於使用者來說是完全透明的。
需要注意的是,任務初始化所耗費的時間,通常取決於回滾機制恢復狀態儲存所用的時間。為了縮短恢復時間,使用者可以將應用程式配置為本地狀態的備用副本。當發生任務遷移時,Kafka流處理會嘗試將任務分配給已存在備用副本的應用程式例項,以減少任務初始化所耗費的時間。

提示:
可以通過設定屬性num.standby.replicas來分配每個任務的備用副本數。

4.總結

通過對Kafka Streams的研究,它的優勢可以總結為以下幾點。首先,它提供了輕量級並且易用的API來有效的降低流資料的開發成本,之前要實現這類處理,需要使用Spark Streaming,Storm,Flink,或者自己編寫Consumer。其次,它開發的應用程式可以支援在YARN,Mesos這類資源排程中,使用方式靈活。而對於非同步操作,不是很友好,需要謹慎處理;另外,對SQL語法的支援有限,需要額外開發。

5.結束語

這篇部落格就和大家分享到這裡,如果大家在研究學習的過程當中有什麼問題,可以加群進行討論或傳送郵件給我,我會盡我所能為您解答,與君共勉!

另外,博主出書了《Kafka並不難學》和《Hadoop大資料探勘從入門到進階實戰》,喜歡的朋友或同學, 可以在公告欄那裡點選購買連結購買博主的書進行學習,在此感謝大家的支援。關注下面公眾號,根據提示,可免費獲取書籍的教學視訊。

相關文章