什么是Flink
Apache Flink是一個分布式大數據處理引擎,可以對有限數據流和無限數據流進行有狀態計算。可部署在各種集群環境,對各種大小的數據規模進行快速計算。
Flink特性
- 支持高吞吐、低延遲、高性能的流式數據處理,而不是用批處理模擬流式處理。
- 支持多種時間窗口,如事件時間窗口、處理時間窗口
- 支持exactly-once語義
- 具有輕量級容錯機制
- 同時支持批處理和流處理
- 在JVM層實現內存優化與管理
- 支持迭代計算
- 支持程序自動優化
- 不僅提供流式處理API,批處理API,還提供了基於這兩層API的高層的數據處理庫
Flink體系架構
Flink運行時主要由JobManager和TaskManager兩個組件組成,Flink架構也遵循主從架構設計原則,JobManager為Master節點,TaskManager為Worker節點。所有組件之間的通信是通過Akka完成,包括任務的狀態以及Checkpoint觸發等信息。
JobManager
JobManager是Flink主從架構中的Master。
JobManager負責分布式任務管理,如任務調度、檢查點、故障恢復等。在高可用分布式部署時,系統中可以有多個JobManager,但是只有一個Leader,其他都是Standby。
TaskManager
TaskManager是Flink主從架構中的worker。
TaskManager負責具體的任務執行和對應任務在每個節點上的資源申請與管理。Flink在運行時至少會存在一個TaskManager。每個TaskManager負責管理其所在節點上的資源信息,如內存、磁盤、網絡,在啟動的時候會將資源的狀態匯報給JobManager。
TaskManager是在JVM中的一個或多個線程中執行任務的工作節點。任務執行的並行度由每個TaskManager上可用的任務槽決定。每個任務代表分給任務槽的一組資源。可以在任務槽中運行一個或多個線程。同一個插槽中的線程共享相同的JVM。同一JVM中的任務共享TCP連接和心跳消息。TaskManager的一個slot代表一個可用線程,該線程具有固定的內存。Flink允許子任務共享Slot,即使它們是不同的task的subtask,只要它們來自相同的job就可以。這種共享可以更好的利用資源。
Client
當用戶提交一個Flink程序時,會首先創建一個Client,該Client首先會對用戶提交的Flink程序進行預處理,並提交到Flink集群中處理,所以Client需要從用戶提交的Flink程序配置中獲取JobManager的地址,並建立到JobManager的連接,將Flink Job提交給JobManager,Client會將用戶提交的Flink程序組裝成一個JobGraph,並且是以JobGraph的形式提交。一個JobGraph是一個Flink Dataflow,它是由多個JobVertex組成的DAG。其中,一個JobGraph包含了一個Flink程序的如下信息:JobID、Job名稱、配置信息、一組JobVertex等。
客戶端通過將編寫好的Flink應用編譯打包,提交到JobManager,然后JobManager會根據已經注冊在JobManager中TaskManager的資源情況,將任務分配給有資源的TaskManager節點,然后啟動並與運行任務。TaskManager從JobManager接收需要部署的任務,然后使用Slot資源啟動Task,建立數據接入的網絡連接,接收數據並開始數據處理。同時TaskManager之間的數據交互都是通過數據流的方式進行的。
Flink組件棧
Flink是一個分層架構的系統,每一層所包含的組件都提供了特定的抽象,用來服務於上層組件。Flink分層的組件棧如下圖所示:
Deployment層
Deployment層主要涉及了Flink的部署模式,Flink支持多種部署模式:
- 本地模式
- 集群模式(Standalone、YARN)
- 雲(GCE/EC2)
Runtime層
Runtime層提供了支持Flink計算的全部核心實現,如:
- 支持分布式Stream處理
- JobGraph到ExecutionGraph的映射、調度等,為上層API層服提供基礎服務
API層
API層主要實現了面向無界Stream的流出來和面向Batch的批處理API。
其中面向流處理對應DataStream API,面向批處理對應DataSet API。
Libraries層
Libraries層也可以稱為Flink應用框架層,根據API層的划分,在API層上構建的滿足特定應用的實現計算框架,也分別對應於面向流處理和面向批處理兩類。
- 面向流處理支持:CEP(復雜事件處理)、基於SQL-like的操作(基於Table的關系操作)
- 面向批處理支持:FlinkML(機器學習庫)、Gelly(圖處理)。
Flink編程模型
流處理與批處理
在大數據領域,批處理任務與流處理任務一般被認為是兩種不同的任務,一個大數據框架一般會被設計為只能處理其中一種任務。例如Storm只支持流處理任務,而MapReduce、Spark支持吃批處理任務。Spark Streaming是Spark之上支持流處理任務的子系統,看似是一個特例,其實Spark Streaming采用的是micro-batch的架構,即把輸入的數據流切分成細粒度的batch,並為每一個batch數據提交一個批處理的Spark任務,所以Spark Streaming本質上還是基於Spark批處理系統對流式數據進行處理,和Storm等完全流式的數據處理方式完全不同。
Flink通過靈活的執行引擎,能夠同時支持批處理和流處理任務。
在執行引擎這一層,流處理系統與批處理系統最大的不同在於節點間的數據傳輸方式。
- 對於一個流處理系統,其節點間數據傳輸的標准模型是:當一條數據被處理完成后,序列化到緩存匯總,然后立刻通過網絡傳輸到下一個節點,由下一個節點急需處理。
- 對於一個批處理系統,其節點間數據傳輸的標准模型是:當一條數據被處理完成后,序列化到緩存中,並不會立刻通過網絡傳輸到下一個節點,當緩存寫滿,就持久化到本地硬盤上,當所有數據都被處理完成后,才開始將處理后的數據通過網絡傳輸到下一個節點。
這兩種數據傳輸模式是兩個極端,對應的是流處理系統對低延遲的要求和批處理系統對高吞吐的要求。
Flink的執行引擎采用了一種十分靈活的方式,同時支持了這兩種數據傳輸模型。
Flink以固定的緩存塊為單位進行網絡數據傳輸,用戶可以通過設置緩存塊超時值指定緩存塊的傳輸時機。
- 如果緩存塊的超時值為0,則Flink的數據傳輸方式類似上文所提到的流處理系統的標准模型,此時系統可以獲得最低的處理延遲。
- 如果緩存塊的超時值為無限大,則Flink的數據傳輸方式類似上文提到批處理系統的標准模型,此時系統可以獲得最高的吞吐量。
- 緩存塊的超時值也可以設置為0到無限大之間的任意值。緩存塊的超時閾值越小,則Flink流處理執行引擎的數據處理延遲越低,但吞吐量也會降低,反之亦然。通過調整緩存塊的超時閾值,用戶可根據需求靈活地權衡系統延遲和吞吐量。
Flink編程接口
Flink根據數據及類型的不同將數據處理結構分為兩大類:
- 支持批處理的計算接口DataSet API
- 支持流計算的計算接口DataStream API
Flink將數據處理接口抽象成四層:
- SQL API:由於SQL語言具有比較低的學習成本,能夠讓數據分析人員和開發人員快速上手,幫助其更加專注業務本身而不受限於復雜的編程接口,可以通過SQL API完成對批計算和流計算的處理。
- Table API:Table API將內存中DataStream和DataSet數據庫在原有的基礎上增加Schema信息,將數據類型統一抽象成表結構,然后通過Table API提供的接口處理對應的數據集。
- DataStream/DataSet API:主要面向具有開發經驗的用戶,用戶可以根據API去處理無界流數據和批量數據。
- Stateful Stream Processing:Stateful Stream Processing是Flink中處理Stateful Stream最底層的接口,可以使用Stateful Stream Processing接口操作狀態、時間等底層數據。Stateful Stream Processing接口很靈活,可以實現非常復雜的流式計算邏輯。
Flink程序結構
下面看下scala寫的Flink wordcount例子:
// 配置執行環境
val env = ExecutionEnvironment.getExecutionEnvironment
// 指定數據源地址,讀取輸入數據
val text = env.readTextFile("/path/to/file")
// 對數據集指定轉換操作邏輯
val counts = text.flatMap { _.toLowerCase.split("\\W+") filter { _.nonEmpty } }
.map { (_, 1) }
.groupBy(0)
.sum(1)
// 指定計算結果輸出位置
counts.writeAsCsv(outputPath, "\n", " ")
// 指定名稱並處罰流式任務
env.execute("Flink WordCount")
從上面可以看出,Flink應用程序基本包含以下5個步驟:
- 配置Flink的執行環境
- 創建和加載數據集
- 對數據集指定轉換操作邏輯、
- 指定計算結果輸出位置
- 調用execute方法觸發程序執行
Flink程序與數據流
Flink程序是由Stream和Transformation這兩個基本構建塊組成,其中Stream是一個中間結果數據,而Transformation是一個操作,它對一個或多個輸出Stream進行計算處理,輸出一個或多個結果Stream。
當一個Flink程序被執行的時候,它會映射為Streaming Dataflow。
一個Streaming Dataflow是由一組Stream和Transformation Operator組成,類似一個DAG圖,在啟動的時候從一個或多個Source Operator開始,結束於一個或多個Sink Operator。
一個由Flink程序映射為Streaming Dataflow的示意圖,如下所示:
FlinkKafkaConsumer是一個Source Operator
map、keyBy、timeWindow、apply是Transformation Operator
RollingSink是一個Sink Operator
Flink應用場景分析
- 優化電商網站的實時搜索結果 阿里巴巴的基礎設置團隊使用Flink實時更新產品細節和庫存信息
- 針對數據分析團隊提供實時流處理服務 通過Flink數據分析憑條提供實時數據分析服務,及時發現問題
- 網絡/傳感器檢測和錯誤檢測 Bouygues電信公司,使用Flink監控其有線和無線網絡,實現快速故障響應
- 商業智能分析ETL Zalando使用Flink轉換數據以便於加載到數據倉庫,將復雜的轉換操作轉化為相對簡單的並確保分析終端用戶可以更快的訪問數據(實時ETL)