1. 程式人生 > >Apache Flink系列(1)-概述

Apache Flink系列(1)-概述

一、設計思想及介紹

基本思想:“一切資料都是流,批是流的特例”

1.Micro Batching 模式

在Micro-Batching模式的架構實現上就有一個自然流資料流入系統進行攢批的過程,這在一定程度上就增加了延時。具體如下示意圖:

 

2.Native Streaming 模式

Native Streaming 計算模式每條資料的到來都進行計算,這種計算模式顯得更自然,並且延時效能達到更低。具體如下示意圖:

很明顯Native Streaming模式佔據了流計算領域 "低延時" 的核心競爭力

當然Native Streaming模式的框架實現上面很容易實現Micro-Batching和Batching模式的計算,Apache Flink就是Native Streaming計算模式的流批統一的計算引擎。

二、豐富的部署模式

Apache Flink 按不同的需求支援Local,Cluster,Cloud三種部署模式,同時Apache Flink在部署上能夠與其他成熟的生態產品進行完美整合,如 Cluster模式下可以利用YARN(Yet Another Resource Negotiator)/Mesos整合進行資源管理,在Cloud部署模式下可以與GCE(Google Compute Engine), EC2(Elastic Compute Cloud)進行整合。

 1.Local 模式

該模式下Apache Flink 整體執行在Single JVM中,在開發學習中使用,同時也可以安裝到很多端類裝置上。

參考

2. Cluster模式

該模式是典型的投產的叢集模式,Apache Flink 既可以Standalone的方式進行部署,也可以與其他資源管理系統進行整合部署,比如與YARN進行整合。

其中JM(JobManager)是Master,TM(TaskManager)是Slave,這種Master/Slave模式有一個典型的問題就是SPOF(single point of failure), SPOF如何解決呢?Apache Flink 又提供了HA(High Availability)方案,也就是提供多個Master,在任何時候總有一個JM服役,N(N>=1)個JM候選,進而解決SPOF問題,示意如下:

 

在實際的生產環境我們都會配置HA方案,目前是基於YARN Cluster的HA方案。

3.Cloud 模式

 該模式主要是與成熟的雲產品進行整合,Apache Flink官網介紹了Google的GCE,Amazon的EC2 ,在Alibaba我們也可以將Apache Flink部署到Alibaba的ECS(Elastic Compute Service)。

三、完善的容錯機制

1.什麼是容錯

容錯(Fault Tolerance) 是指容忍故障,在故障發生時能夠自動檢測出來並使系統能夠自動回覆正常執行。當出現某些指定的網路故障、硬體故障、軟體錯誤時,系統仍能執行規定的一組程式,或者說程式不會因系統中的故障而中止,並且執行結果也不會因系統故障而引起計算差錯。

2.容錯的處理模式

在一個分散式系統中由於單個程序或者節點宕機都有可能導致整個Job失敗,那麼容錯機制除了要保證在遇到非預期情況系統能夠"執行"外,還要求能"正確執行",也就是資料能按預期的處理方式進行處理,保證計算結果的正確性。計算結果的正確性取決於系統對每一條計算資料處理機制,一般有如下三種處理機制:

  • At Most Once:最多消費一次,這種處理機制會存在資料丟失的可能。
  • At Least Once:最少消費一次,這種處理機制資料不會丟失,但是有可能重複消費。
  • Exactly Once:精確一次,無論何種情況下,資料都只會消費一次,這種機制是對資料準確性的最高要求,在金融支付,銀行賬務等領域必須採用這種模式。

3.Apache Flink的容錯機制

Apache Flink的Job會涉及到3個部分,外部資料來源(External Input), Flink內部資料處理(Flink Data Flow)和外部輸出(External Output)。如下示意圖:

目前Apache Flink 支援兩種資料容錯機制:

  • At Least Once
  • Exactly Once

其中 Exactly Once 是最嚴格的容錯機制,該模式要求每條資料必須處理且僅處理一次。那麼對於這種嚴格容錯機制,一個完整的Flink Job容錯要做到 End-to-End 的 容錯必須結合三個部分進行聯合處理,根據上圖我們考慮三個場景:

場景一:Flink的Source Operator 在讀取到Kafla中pos=2000的資料時候,由於某種原因宕機了,這個時候Flink框架會分配一個新的節點繼續讀取Kafla資料,那麼新的處理節點怎樣處理才能保證資料處理且只被處理一次呢?

場景二:Flink Data Flow內部某個節點,如果上圖的agg()節點發生問題,在恢復之後怎樣處理才能保持map()流出的資料處理且只被處理一次?

 

場景三:Flink的Sink Operator 在寫入Kafka過程中自身節點出現問題,在恢復之後如何處理,計算結果才能保證寫入且只被寫入一次?

4.系統內部容錯

Apache Flink利用Checkpointing機制來處理容錯,Checkpointing的理論基礎 Stephan 在 Lightweight Asynchronous Snapshots for Distributed Dataflows 進行了細節描述,該機制源於有K. MANI CHANDY和LESLIE LAMPORT 發表的 Determining-Global-States-of-a-Distributed-System Paper。Apache Flink 基於Checkpointing機制對Flink Data Flow實現了At Least Once 和 Exactly Once 兩種容錯處理模式。
Apache Flink Checkpointing的內部實現會利用 Barriers,StateBackend等後續章節會詳細介紹的技術來將資料的處理進行Marker。Apache Flink會利用Barrier將整個流進行標記切分,如下示意圖:

這樣Apache Flink的每個Operator都會記錄當前成功處理的Checkpoint,如果發生錯誤,就會從上一個成功的Checkpoint開始繼續處理後續資料。比如 Soruce Operator會將讀取外部資料來源的Position實時的記錄到Checkpoint中,失敗時候會從Checkpoint中讀取成功的position繼續精準的消費資料。每個運算元會在Checkpoint中記錄自己恢復時候必須的資料,比如流的原始資料和中間計算結果等資訊,在恢復的時候從Checkpoint中讀取並持續處理流資料。

5.外部Source容錯

Apache Flink 要做到 End-to-End 的 Exactly Once 需要外部Source的支援,比如上面我們說過 Apache Flink的Checkpointing機制會在Source節點記錄讀取的Position,那就需要外部資料提供讀取的Position和支援根據Position進行資料讀取。

6.外部Sink容錯

 Apache Flink 要做到 End-to-End 的 Exactly Once 相對比較困難,如上場景三所述,當Sink Operator節點宕機,重新恢復時候根據Apache Flink 內部系統容錯 exactly once的保證,系統會回滾到上次成功的Checkpoin繼續寫入,但是上次成功Checkpoint之後當前Checkpoint未完成之前已經把一部分新資料寫入到kafka了. Apache Flink自上次成功的Checkpoint繼續寫入kafka,就造成了kafka再次接收到一份同樣的來自Sink Operator的資料,進而破壞了End-to-End 的 Exactly Once 語義(重複寫入就變成了At Least Once了),如果要解決這一問題,Apache Flink 利用Two phase commit(兩階段提交)的方式來進行處理。本質上是Sink Operator 需要感知整體Checkpoint的完成,並在整體Checkpoint完成時候將計算結果寫入Kafka。

四、流批統一的計算引擎

批與流是兩種不同的資料處理模式,如Apache Storm只支援流模式的資料處理,Apache Spark只支援批(Micro Batching)模式的資料處理。那麼Apache Flink 是如何做到既支援流處理模式也支援批處理模式呢?

1.統一的資料傳輸層

開篇我們就介紹Apache Flink 的 "命脈"是以"批是流的特例"為導向來進行引擎的設計的,系統設計成為 "Native Streaming"的模式進行資料處理。那麼Apache FLink將批模式執行的任務看做是流式處理任務的特殊情況,只是在資料上批是有界的(有限數量的元素)。

Apache Flink 在網路傳輸層面有兩種資料傳輸模式:

  • PIPELINED模式 - 即一條資料被處理完成以後,立刻傳輸到下一個節點進行處理。
  • BATCH 模式 - 即一條資料被處理完成後,並不會立刻傳輸到下一個節點進行處理,而是寫入到快取區,如果快取寫滿就持久化到本地硬碟上,最後當所有資料都被處理完成後,才將資料傳輸到下一個節點進行處理。

對於批任務而言同樣可以利用PIPELINED模式,比如我要做count統計,利用PIPELINED模式能拿到更好的執行效能。只有在特殊情況,比如SortMergeJoin,這時候我們需要全域性資料排序,才需要BATCH模式。大部分情況流與批可用統一的傳輸策略,只有特殊情況,才將批看做是流的一個特例繼續特殊處理。

2.統一任務排程層

Apache Flink 在任務排程上流與批共享統一的資源和任務排程機制(後續)

3.統一的使用者API層

Apache Flink 在DataStremAPI和DataSetAPI基礎上,為使用者提供了流批統一的上層TableAPI和SQL,在語法和語義上流批進行高度統一。(其中DataStremAPI和DataSetAPI對流和批進行了分別抽象,這一點並不優雅,在Alibaba內部對其進行了統一抽象)。

4.求同存異

Apache Flink 是流批統一的計算引擎,並不意味著流與批的任務都走統一的code path,在對底層的具體運算元的實現也是有各自的處理的,在具體功能上面會根據不同的特性區別處理。比如 批沒有Checkpoint機制,流上不能做SortMergeJoin。

五、Apache Flink 架構

 1.元件棧

我們上面內容已經介紹了很多Apache Flink的各種元件,下面我們整體概覽一下全貌,如下:

TableAPI和SQL都建立在DataSetAPI和DataStreamAPI的基礎之上,那麼TableAPI和SQL是如何轉換為DataStream和DataSet的呢?

2.TableAPI&SQL到DataStrem&DataSet的架構

TableAPI&SQL最終會經過Calcite優化之後轉換為DataStream和DataSet,具體轉換示意如下:

對於流任務最終會轉換成DataStream,對於批任務最終會轉換成DataSet。

3.ANSI-SQL的支援

Apache Flink 之所以利用ANSI-SQL作為使用者統一的開發語言,是因為SQL有著非常明顯的優點,如下:

  • Declarative - 使用者只需要表達我想要什麼,不用關心如何計算。
  • Optimized - 查詢優化器可以為使用者的 SQL 生成最優的執行計劃,獲取最好的查詢效能。
  • Understandable - SQL語言被不同領域的人所熟知,用SQL 作為跨團隊的開發語言可以很大地提高效率。
  • Stable - SQL 是一個擁有幾十年歷史的語言,是一個非常穩定的語言,很少有變動。
  • Unify - Apache Flink在引擎上對流與批進行統一,同時又利用ANSI-SQL在語法和語義層面進行統一。

4.無限擴充套件的優化機制

Apache Flink 利用Apache Calcite對SQL進行解析和優化,Apache Calcite採用Calcite是開源的一套查詢引擎,實現了兩套Planner:

  • HepPlanner - 是RBO(Rule Base Optimize)模式,基於規則的優化。
  • VolcanoPlanner - 是CBO(Cost Base Optimize)模式,基於成本的優化。

Flink SQL會利用Calcite解析優化之後,最終轉換為底層的DataStrem和Dataset。上圖中 Batch rules和Stream rules可以根據優化需要無限新增優化規則。

5.豐富的類庫和運算元

類庫:

  • CEP - 複雜事件處理類庫,核心是一個狀態機,廣泛應用於事件驅動的監控預警類業務場景。
  • ML - 機器學習類庫,機器學習主要是識別資料中的關係、趨勢和模式,一般應用在預測類業務場景。
  • GELLY - 圖計算類庫,圖計算更多的是考慮邊和點的概念,一般被用來解決網狀關係的業務場景。

運算元:

Apache Flink 提供了豐富的功能運算元,對於資料流的處理來講,可以分為單流處理(一個數據源)和多流處理(多個數據源)。

6.多流操作

 

  • UNION - 將多個欄位型別一致資料流合併為一個數據流,如下示意:
    image
  • JOIN - 將多個數據流(資料型別可以不一致)聯接為一個數據流,如下示意:
    image

如上通過UION和JOIN我們可以將多流最終變成單流,Apache Flink 在單流上提供了更多的操作運算元。

 7.單流操作

 

將多流變成單流之後,我們按資料輸入輸出的不同歸類如下:

型別 輸入 輸出 Table/SQL運算元 DataStream/DataSet運算元
Scalar Function 1 1 Built-in & UDF, Map
Table Function 1 N(N>=0) Built-in & UDTF FlatMap
Aggregate Function N(N>=0) 1 Built-in & UDAF Reduce

如上表格對單流上面操作做簡單歸類,除此之外還可以做 過濾,排序,視窗等操作,後續章節會逐一介紹。

 8.存在的問題

 

Apache Flink 目前的架構還存在很大的優化空間,比如前面提到的DataStreamAPI和DataSetAPI其實是流與批在API層面不統一的體現,同時看具體實現會發現DataStreamAPI會生成Transformation tree然後生成StreamGraph,最後生成JobGraph,底層對應StreamTask,但DataSetAPI會形成Operator tree,flink-optimize模組會對Batch Plan進行優化,形成Optimized Plan 後形成JobGraph,最後形成BatchTask。具體示意如下:
image

這種情況其實 DataStreamAPI到Runtime 和 DataSetAPI到Runtime的實現上並沒有得到最大程度的統一和複用。在這一點上面Aalibab 企業版的Flink在架構和實現上都進行了進一步優化。

 六、小結

本篇概要的介紹了"批是流的特例"這一設計觀點是Apache Flink的"命脈",它決定了Apache Flink的執行模式是純流式的,這在實時計算場景的"低延遲"需求上,相對於Micro Batching模式佔據了架構的絕對優勢。

介紹了Apache Flink的部署模式,容錯處理,引擎的統一性和Apache Flink的架構。