帶你玩轉Flink流批一體分散式實時處理引擎

華為雲開發者社群發表於2022-01-17
摘要:Apache Flink是為分散式、高效能的流處理應用程式打造的開源流處理框架。

本文分享自華為雲社群《【雲駐共創】手把手教你玩轉Flink流批一體分散式實時處理引擎》,作者: 萌兔之約。

Apache Flink是為分散式、高效能的流處理應用程式打造的開源流處理框架。Flink不僅能提供同時支援高吞吐和exactly-once語義的實時計算,還能提供批量資料處理。相較於市面上的其他資料處理引擎,它採用的是基於流計算來模擬批處理。

一、Flink原理及架構

Flink簡介

Apache Flink是為分散式、高效能的流處理應用程式打造的開源流處理框架。Flink不僅能提供同時支援高吞吐和exactly-once語義的實時計算,還能提供批量資料處理。主要由Java程式碼實現,支援實時流處理和批處理,批資料只是流資料的一個極限案例。支援了迭代計算,記憶體管理和程式優化。

帶你玩轉Flink流批一體分散式實時處理引擎

相較於市面上的其他資料處理引擎,Flink和Spark都可以同時支援流處理和批處理。但是,Spark的技術理念是基於批處理來模擬流的計算;而Flink則完全相反,它採用的是基於流計算來模擬批處理。

Flink關鍵機制

帶你玩轉Flink流批一體分散式實時處理引擎

四個機制:狀態、時間、檢查點、視窗

Flink中有四種最重要的關鍵機制,這些關鍵機制在後面我們也會來進行詳細的介紹,這裡我們主要介紹它的基本概念以及主要用途。首先Flink中最重要的一個機制是狀態機制(State),Flink是一種有狀態的流計算引擎。狀態的作用主要是我們Flink是一種流計算,它需要儲存節點的中間計算結果。另外狀態的儲存還有利於Flink進行容錯恢復。狀態有密切關係的是Flink的Checkpoint,也就是檢查點的機制,Checkpoint能夠去把Flink的狀態進行儲存,相當於是做一次快照,方便Flink進行容錯恢復。另外因為Flink它是一種流計算引擎,它的資料是不間斷產生的,是沒有界限的,因此我們需要有一種機制能夠對資料進行切分,我們會採用的時間(Time)作為切分點,另外Flink進行容錯性的恢復,它也需要知道從哪個時間點來進行恢復。所以說時間也是Flink中一種很重要的機制。最後是視窗window,在Flink中需要使用的視窗對資料進行切分,也方便對資料進行聚合計算。

Flink核心理念

Flink與其他流計算引擎的最大區別,就是狀態管理。

Flink提供了內建的狀態管理,可以把工作時狀態儲存在Flink內部,而不需要把它儲存在外部系統。這樣做的好處:

  • 降低了計算引擎對外部系統的依賴,使得部署、運維更加簡單;
  • 對效能帶來了極大的提升。

Flink Runtime整體架構

帶你玩轉Flink流批一體分散式實時處理引擎

Flink執行時架構從下至上可以分為了三層,在最下層是Flink的一些配置方式,Flink可以採用單機的方式安裝,也可以採用的叢集的方式安裝,另外也可以採用雲的方式部署。在大多數情況下,Flink都是採用的叢集的方式進行配置和安裝的。其中呢它支援了兩種叢集模式,一種是Standalon,這種方式是採用了Flink自身提供的資源排程管理器。另外一種方式是基於YARN的方式進行了配置安裝。

YARN提供了專用的資源管理器。在中間層次是Flink的計算引擎,這個計算引擎它同時能夠支援流處理和批處理,可以接收了上層的api提交給它做作業 。Runtime這個引擎上面可以分為了兩個模組,一個模組是DataStream api,一個是DataSet api。Flink向dataset和datastream,也就是批資料集以及流資料集是分開處理的,但是都是公用下面的計算引擎。基於兩種型別的api,Flink又提供了更多的上層的抽象的api,API越抽象,它的表達能力越弱,但是它對資料的處理能力、抽象性也越強。在針對於上層Table api和SQL,它是主要是針對關係運算的,那針對關係資料的查詢,Flink提供了統一的介面,基於流資料api,同時提供了複雜事件處理api。複雜事件指的就是說對不能夠用時間去表示事件的開始、次序以及結束這樣的事件進行處理的api介面。另外針對於資料及api,它提供了機器學習api以及圖計算的api。

Flink核心概念- DataStream

帶你玩轉Flink流批一體分散式實時處理引擎

DataStream: Flink用類DataStream來表示程式中的流式資料。使用者可以認為它們是含有重複資料的不可修改的集合(collection),DataStream中元素的數量是無限的。

從圖中我們可以發現,對DataStream可以使用一些運算元,例如KeyBy這樣的運算元,對它進行處理轉換之後,它會轉換成另外一種資料流,也稱為keyedstream。那麼基於keyedstream,我們進一步可以使用視窗運算元,這主要是Flink程式設計中對資料流的一些處理方式。

Flink核心概念- DataSet

DataSet : Flink系統可對資料集進行轉換(例如,過濾,對映,聯接,分組),資料集可從讀取檔案或從本地集合建立。結果通過接收器( Sink)返回,接收器可以將資料寫入(分散式)檔案或標準輸出(例如命令列終端)

Flink程式

帶你玩轉Flink流批一體分散式實時處理引擎

Flink程式由Source、Transformation和Sink三部分組成,其中Source主要負責資料的讀取,支援HDFS、kafka和文字等;Transformation主要負責對資料的轉換操作; Sink負責最終資料的輸出,支援HDFS、kafka和文字輸出等。在各部分之間流轉的資料稱為流( stream ) 。

Flink資料來源

批處理:

Files:HDFS,Local file system,MapR file system;Text,CSV,Avro,Hadoop input formats

JDBC、HBase和 Collections

流處理:

Files、Socket streams、Kafka、RabbitMQ、Flume、Collections、 Implement your own和SourceFunction.collecto

Flink程式執行圖

帶你玩轉Flink流批一體分散式實時處理引擎

Flink是一種master-Slave架構,它在啟動的時候就會產生了JobManger以及TaskManager。事實上在Flink程式中還包含兩個元件,這兩個元件一個叫resource manager,主要負責了資源的排程與管理,另外一個稱為Dispatcher。主要是用來進行client,要把JobManager進行分發公佈。我們來看一看具體的執行流程。

首先是使用者提交Flink程式,這個Flink程式就會轉換成邏輯資料流圖。客戶端接收到邏輯資料流圖之後,然後連同jar包以及一些依賴包就會提交給了JobManger,JobManger接收到邏輯資料流圖之後會轉成物理資料流圖,這個物理資料流圖是真實的可執行的,能夠具體的將任務放置在TaskManager上,在TaskManager中會將它所擁有的資源劃分成一個一個的TaskSlot。每個TaskSlot實際上就相當於是jvm,它的一個具體的執行緒。每個TaskSlot佔用了TaskManager的一部分資源,這裡的資源主要是以記憶體進行劃分的,TaskSlot不對cpu的資源進行劃分,因此沒有對cpu的資源進行隔離。

Flink作業執行流程(一)

帶你玩轉Flink流批一體分散式實時處理引擎

使用者首先提交Flink程式到JobClient,經過JobClient的處理、解析、優化提交到JobManager,最後由TaskManager執行task。

在Flink中它通過了JobClient提交了任務,做過JobClient提交的任務進一步的進行優化、解析以及處理,提交給了JobManager。JobManager會將jobClient提交了邏輯資料流圖轉換成物理資料流圖,然後將這些任務分配給taskmanager。taskmanager接受到任務之後就相應地進行處理,並且彙報了task的狀態給JobManager,JobManager最後就把結果反饋給jobClient。

JobClient是Flink程式和JobManager互動的橋樑。主要負責接收程式、解析程式的執行計劃、優化程式的執行計劃,然後提交執行計劃到JobManager。在Flink中主要有三類Operator。

Source Operator:資料來源操作,比如檔案、socket、Kafka等。

Transformation Operator:資料轉換操作,比如map,flatMap,reduce等運算元。

Sink Operator:資料儲存操作。比如資料儲存到HDFS、Mysql、Kafka等等。

一個完整的Flink程式---java

帶你玩轉Flink流批一體分散式實時處理引擎帶你玩轉Flink流批一體分散式實時處理引擎

Flink的資料處理

Apache Flink它同時支援批處理和流處理,也能用來做一些基於事件的應用。

首先Flink是一個純流式的計算引擎,它的基本資料模型是資料流。流可以是無邊界的無限流,即一般意義上的流處理。也可以是有邊界的有限流,就是批處理。因此Flink用一套架構同時支援了流處理和批處理。

其次,Flink的一個優勢是支援有狀態的計算。如果處理一個事件(或一條資料)的結果只跟事6件本身的內容有關,稱為無狀態處理;反之結果還和之前處理過的事件有關,稱為有狀態處理。

有界流與無界流

無界流:有定義流的開始,但沒有定義流的結束。資料來源會無休止地產生資料。無界流的資料必須持續處理,即資料被讀取後需要立刻處理。不能等到所有資料都到達再處理,因為輸入是無限的,在任何時候輸入都不會完成。處理無界資料通常要求以特定順序攝取事件,例如事件發生的順序,以便能夠推斷結果的完整性。

帶你玩轉Flink流批一體分散式實時處理引擎

有界流:有定義流的開始,也有定義流的結束。有界流可以在讀取所有資料後再進行計算。有界流所有資料可以被排序,所以並不需要有序攝取。有界流處理通常被稱為批處理。

批處理示例

帶你玩轉Flink流批一體分散式實時處理引擎

批處理是流處理的一種非常特殊的情況。在流處理中,我們為資料定義滑動視窗或滾動視窗,並且在每次視窗滑動或滾動時生成結果。批處理則不同,我們定義一個全域性視窗,所有的記錄都屬於同一個視窗。舉例來說,以下程式碼表示一個簡單的Flink程式,它負責每小時對某網站的訪問者計數,並按照地區分組。

如果知道輸入資料是有限的,則可以通過以下程式碼實現批處理。

帶你玩轉Flink流批一體分散式實時處理引擎

如果輸入資料是有限的,那麼下面程式碼與上面程式碼的執行結果相同。

帶你玩轉Flink流批一體分散式實時處理引擎

Flink批處理模型

帶你玩轉Flink流批一體分散式實時處理引擎

Flink通過一個底層引擎同時支援流處理和批處理。

在流處理引擎之上,Flink 有以下機制:

  • 檢查點機制和狀態機制:用於實現容錯、有狀態的處理;
  • 水印機制:用於實現事件時鐘;
  • 視窗和觸發器:用於限制計算範圍,並定義呈現結果的時間。

在同一個流處理引擎之上,Flink 還存在另一套機制,用於實現高效的批處理。

  • 用於排程和恢復的回溯法:由 Microsoft Dryad 引入,現在幾乎用於所有批處理器;
  • 用於雜湊和排序的特殊記憶體資料結構:可以在需要時,將一部分資料從記憶體溢位到硬碟上;
  • 優化器:儘可能地縮短生成結果的時間。

流與批處理機制

兩套機制分別對應各自的API(DataStream API 和 DataSet API);在建立 Flink 作業時,並不能通過將兩者混合在一起來同時 利用 Flink 的所有功能。

Flink支援兩種關係型的API,Table APl和sQL。這兩個API都是批處理和流處理統一的APl,這意味著在無邊界的實時資料流和有邊界的歷史記錄資料流上,關係型API會以相同的語義執行查詢,併產生相同的結果。

  • Table API / SQL 正在以流批統一的方式成為分析型用例的主要 API。
  • DataStream API 是資料驅動應用程式和資料管道的主要API。

二、Flink的Time與Window

時間背景

在流處理器程式設計中,對於時間的處理是非常關鍵的。比如計數的例子,事件流資料(例如伺服器日誌資料、網頁點選資料和交易資料)不斷產生,我們需要用key將事件分組,並且每隔一段時間就針對每一個key對應的事件計數。這就是我們熟知的“大資料”應流處理中的時間分類

在資料流處理過程中,我們經常使用系統處理時間即: processing time作為某個事件的時間,而實際上系統時間processing time是我們強加給事件的時間,由於網路延遲等原因並不能較好的反應事件之間發生的先後順序。

在實際場景中,每個事件的時間可以分為三種:

  • event time,即事件發生時的時間;
  • ingestion time,即事件到達流處理系統的時間;
  • processing time,即事件被系統處理的時間。

三種時間示例

例如,一條日誌進入Flink的時間為2019-11-1210:00:00.123,到達window的系統時間為2019-11-1210:00:01.234,日誌的內容如下:

2019-11-0218:37:15.624 INFO Fail over to rm2

2019-11-0218:37:15.624是Event Time;

2019-11-1210:00:00.123是Ingestion Time;

2019-11-1210:00:01.234是Processing Time;

三種時間的區別

實際情況中事件真正發生的先後順序與系統處理時間存在一定的差異,這些差異主要由網路延遲、處理時間的長短等造成。如圖所示:

帶你玩轉Flink流批一體分散式實時處理引擎

橫座標代表Event time,縱座標代表processing time。理想情況下,eventtime和processing time構成的座標應該形成一條傾斜角為45度的線。但實際應用過程中,processing time要落後與eventtime,造成事件到來的先後順序不一致。

Flink支援的時間語義

帶你玩轉Flink流批一體分散式實時處理引擎

Processing Time是指事件資料被Operator處理時所在機器的系統時間,它提供了最好的效能和最低的延遲。

Event Time是指在資料產生時該裝置上對應的時間,這個時間在進入Flink之前已經存在於資料記錄中了。

Ingestion Time指的是事件資料進入到Flink的時間。

Window概述

流式計算是一種被設計用於處理無限資料集的資料處理引擎,而無限資料集是指一種不斷增長的本質上無限的資料集,而Window是一種切割無限資料為有限塊進行處理的手段。Window是無限資料流處理的核心,它將一個無限的stream拆分成有限大小的"buckets"桶,我們可以在這些桶上做計算操作。

Window型別

Window根據應用型別可以分成兩類:

  • CountWindow:資料驅動,按照指定的資料條數生成一個Window,與時間無關。
  • TimeWindow:時間驅動,按照時間生成Window。

Apache Flink是一個天然支援無限流資料處理的分散式計算框架,在Flink中 Window可以將無限流切分成有限流。Flink中 Window可以是Time Window,也可以是Count Window。

TimeWindow分類

TimeWindow可以根據視窗實現原理的不同分成三類:滾動視窗(Tumbling Window ) .滑動視窗( Sliding Window)和會話視窗( Session Window)。

滾動視窗

將資料依據固定的視窗長度對資料進行切片。特點:時間對齊,視窗長度固定,沒有重疊。

適用場景:適合做Bl統計等(做每個時間段的聚合計算)。

舉一個例子,假設要對感測器輸出的數值求和。一分鐘滾動視窗收集最近一分鐘的數值,並在一分鐘結束時輸出總和,如下圖所示。

帶你玩轉Flink流批一體分散式實時處理引擎

滑動視窗

滑動視窗是固定視窗的更廣義的一種形式,滑動視窗由固定的視窗長度和滑動間隔組成。特點∶時間對齊,視窗長度固定,有重疊。

適用場景:對最近一個時間段內的統計(求某介面最近5min的失敗率來決定是否要報警)。

示例:一分鐘滑動視窗計算最近一分鐘的數值總和,但每半分鐘滑動一次並輸出結果,如下圖所示。

帶你玩轉Flink流批一體分散式實時處理引擎

會話視窗

會話視窗由一系列事件組合一個指定時間長度的timeout間隙組成,類似於web應用的session,也就是一段時間沒有接收到新資料就會生成新的視窗。特點:時間無對齊。

帶你玩轉Flink流批一體分散式實時處理引擎

程式碼定義

在Flink中,一分鐘滾動視窗的定義如下:

stream.timeWindow(Time.minutes(1));

在Flink中,每半分鐘(即30秒)滑動一次的一分鐘滑動視窗,如下所示:

stream.timeWindow(Time.minutes(1),Time.seconds(30));

三、Flink的Watermark

亂序問題

流處理從事件產生,到流經source,再到operator,中間是有一個過程和時間的,雖然大部分情況下,流到operator的資料都是按照事件產生的時間順序來的,但是也不排除由於網路、分散式等原因,導致亂序的產生,所謂亂序,就是指Flink接收到的事件的先後順序不是嚴格按照事件的Event Time順序排列的。

帶你玩轉Flink流批一體分散式實時處理引擎

此時出現一個問題,一旦出現亂序,如果只根據eventTime決定window的執行,我們不能明確資料是否全部到位,但又不能無限期的等下去,此時必須要有個機制來保證一個特定的時間後,必須觸發window去進行計算了,這個特別的機制,就是Watermark。

亂序示例

例子:某App會記錄使用者的所有點選行為,並回傳日誌(在網路不好的情況下,先儲存在本地,延後回傳)。A使用者在11:02對App進行操作,B使用者在11:03對App進行操作,但是A使用者的網路不太穩定,回傳日誌延遲了,導致我們在服務端先接受到B使用者11:03的訊息,然後再接受到A使用者11:02的訊息,訊息亂序了。

水位線(Watermark)

對於無窮資料集,我們缺乏一種有效的方式來判斷資料完整性,因此就有了Watermark,它是建立在事件時間上的一個概念,用來刻畫資料流的完整性。如果按照處理時間來衡量事件,一切都是有序的、完美的,自然而然也就不需要Watermark了。換句話說事件時間帶來了亂序的問題,而Watermark就是用來解決亂序問題。所謂的亂序,其實就是有事件延遲了,對於延遲的元素,我們不可能無限期的等下去,必須要有一種機制來保證一個特定的時間後,必須觸發Window進行計算。這個特別的機制,就是Watermark,它告訴了運算元延遲到達的訊息不應該再被接收。

  • Watermark是一種衡量Event Time進展的機制。
  • Watermark是用於處理亂序事件的,而正確的處理亂序事件,通常用Watermark機制結合window來實現。
  • 資料流中的Watermark用於表示timestamp小於Watermark的資料,都已經到達了,因此,window的執行也是由Watermark觸發的。
  • Watermark可以理解成一個延遲觸發機制,我們可以設定Watermark的延時時長t,每次系統會校驗已經到達的資料中最大的maxEventTime,然後認定eventTime小於maxEventTime - t的所有資料都已經到達,如果有視窗的停止時間等於maxEventTime – t,那麼這個視窗被觸發執行。
  • watermark 用來讓程式自己平衡延遲和結果正確性

Watermark的原理

Flink怎麼保證基於event-time的視窗在銷燬的時候,已經處理完了所有的資料呢?

帶你玩轉Flink流批一體分散式實時處理引擎

這就是watermark的功能所在。watermark會攜帶一個單調遞增的時間戳t,Watermark(t)表示所有時間戳不大於t的資料都已經到來了,未來小於等於t的資料不會再來,因此可以放心地觸發和銷燬視窗了。

帶你玩轉Flink流批一體分散式實時處理引擎

當Flink,接收到資料時,會按照一定的規則去生成Watermark,這條Watermark就等於當前所有到達資料中的maExertT me"-延N時長,也就定說,Watermark是基於資料攜帶的時間戳生成的,一旦Watermark比當前未觸發的視窗的停止時間要晚,那麼就會觸發相應視窗的執行。由於eventtime是由資料攜帶的,因此,如果執行過程中無法獲取新的資料,那麼沒有被觸發的視窗將永遠都不被觸發。

上圖中,我們設定的允許最大延遲到達時間為2s,所以時間戳為7s的事件對應的Watermark 是 5s,時間戳為12s的事件的Watermark是10s,如果我們的視窗是1s-5s,視窗2是6s~-10s,那麼時間戳為7s的事件到達時的Matermarker.恰好觸發視窗1,時間戳為 12s的事件到達時的Watermark恰好觸發視窗2。

Watermark就是觸發前一視窗的“關窗時間”,一旦觸發關門那麼以當前時刻為準在視窗範圍內的所有所有資料都會收入窗中。只要沒有達到水位那麼不管現實中的時間推進了多久都不會觸發關窗。

延遲的資料

Watermark能夠應對亂序的資料,但是真實世界中沒法得到一個完美的 Watermark數值。要麼沒法獲取到,要麼耗費太大,因此實際工作中會近似 Watermark(t)之後,還有較小的概率接受到時間戳t之前的資料,在Flink中將這些資料定義為“late elements”,同樣可以在Window中指定允許延遲的最大時間(預設為О),可以使用下面的程式碼進行設定:

帶你玩轉Flink流批一體分散式實時處理引擎

延遲資料處理機制

延遲事件是亂序事件的特例,和一般亂序事件不同的是它們的亂序程度超出了水位線( Watermark)的預計,導致視窗在它們到達之前已經關閉。

延遲事件出現時視窗已經關閉併產出了計算結果,對於此種情況處理的方法有3種:

  • 重新啟用已經關閉的視窗並重新計算以修正結果。
  • 將延遲事件收集起來另外處理。
  • 將延遲事件視為錯誤訊息並丟棄。

Flink預設的處理方式是第3種直接丟棄,其他兩種方式分別使用Side Output和AllowedLateness。

Side Output機制

Side Output機制可以將延遲事件單獨放入一個資料流分支,這會作為Window計算結果的副產品,以便使用者獲取並對其進行特殊處理。

side Output獲取延遲資料:

設定allowedLateness之後,遲來的資料同樣可以觸發視窗,進行輸出,利用Flink的sideoutput機制,可以獲取到這些延遲的資料,使用方式如下:

帶你玩轉Flink流批一體分散式實時處理引擎

Allowed Lateness機制

Allowed Lateness機制允許使用者設定一個允許的最大延遲時長。Flink會在視窗關閉後一直儲存視窗的狀態直至超過允許延遲時長,這期間的延遲事件不會被丟棄,而是預設會觸發視窗重新計算。因為儲存視窗狀態需要額外記憶體,並且如果視窗計算使用了ProcessWindowFunction APl還可能使得每個延遲事件觸發一次視窗的全量計算,代價比較大,所以允許延遲時長不宜設得太長,延遲事件也不宜過多。

四、Flink的容錯

Flink容錯機制

為了保證程式的容錯恢復以及程式啟動時其狀態恢復,Flink任務都會開啟Checkpoint或者觸發Savepoint進行狀態儲存。

  • Checkpoint機制。這種機制保證了實時程式執行時,即使突然遇到異常也能夠進行自我恢復。Checkpoint對於使用者層面,是透明的,使用者會感覺不到Checkpoint過程的存在。
  • Savepoint機制。是在某個時間點程式狀態全域性映象,以後程式在進行升級,或者修改併發度等情況,還能從儲存的狀態位繼續啟動恢復。Savepoint可以看做是Checkpoint在特定時期的一個狀態快照。

Checkpoint

Flink 如何保證exactly-once呢?它使用一種被稱為“檢查點( Checkpoint )”的特性,在出現故障時將系統重置回正確狀態。Flink狀態儲存主要依靠Checkpoint機制,Checkpoint會定時製作分散式快照,對程式中的狀態進行備份。

Checkpoint檢查點機制

Flink中基於非同步輕量級的分散式快照技術提供了Checkpoints容錯機制,分散式快照可以將同一時間點Task/Operator的狀態資料全域性統一快照處理。Flink會在輸入的資料集上間隔性地生成checkpoint barrier,通過棚欄( barrier)將間隔時間段內的資料劃分到相應的checkpoint中。當應用出現異常時,Operator就能夠從上一次快照中恢復所有運算元之前的狀態,從而保證資料的一致性。

對於狀態佔用空間比較小的應用,快照產生過程非常輕量,高頻率建立且對Flink任務效能影響相對較小。Checkpoint過程中狀態資料一般被儲存在一個可配置的環境中,通常是在JobManager節點或HDFS上。

Checkpoint配置

帶你玩轉Flink流批一體分散式實時處理引擎

預設情況下Flink不開啟檢查點,使用者需要在程式中通過呼叫enableCheckpointing(n)方法配置和開啟檢查點,其中n為檢查點執行的時間間隔,單位為毫秒。

exactly-once和at-least-once語義選擇

exactly-once:保證端到端資料一致性,資料要求高,不允許出現資料丟失和資料重複,Flink的效能也相對較弱;

at-least-once:時延和吞吐量要求非常高但對資料的一致性要求不高的場景。

Flink預設使用exactly-once模式,可以通過setCheckpointingMode()方法來設定語義模式。

env.getCheckpointConfig().setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE)

Checkpoint超時時間

指定每次Checkpoint執行過程中的上限時間範圍,一旦Checkpoint執行時間超過該閾值,Flink將會中斷Checkpoint過程,並按照超時處理。

該指標可以通過setCheckpointTimeout方法設定,預設10分鐘。

env.getCheckpointConfig().setCheckpointingTimeout(60000)

檢查點之間最小時間間隔

設定兩個Checkpoint之間的最小時間間隔,防止出現狀態資料過大而導致Checkpoint執行時間過長,從而導致Checkpoint積壓過多,最終Flink應用密集地觸發Checkpoint操作,會佔用大量計算資源而影響到整個應用的效能。

env.getCheckpointConfig().setMinPauseBetweenCheckpoints(500)

最大並行執行的檢查點數量

設定能夠同時執行的Checkpoint數量。在預設情況下只有一個檢查點可以執行,根據使用者指定的數量可以同時觸發多個Checkpoint,從而提升Checkpoint整體的效率。

env.getCheckpointConfig().setMaxConcurrentCheckpoints(500)

外部檢查點

設定週期性的外部檢查點,然後將狀態資料持久化到外部系統中,使用這種方式不會在任務停止的過程中清理掉檢查點資料,而是一直儲存在外部系統介質中,也可以通過從外部檢查點中對任務就行恢復。

env.getCheckpointConfig().enableExternalizedCheckpoints(ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION)

作業如何恢復資料?

Flink在Cancel時允許在外部介質保留Checkpoint;另一方面,Flink還有另外一個機制是SavePoint.

Savepoints是檢查點的一種特殊實現,底層其實是使用Checkpoints的機制。Savepoints是使用者以手工命令的方式觸發,並將結果持久化到指定的儲存路徑中,目的是幫助使用者在升級和維護叢集過程中儲存系統中的狀態資料,避免因為停機運維或者升級應用等正常終止應用的操作而導致系統無法恢復到原有的計算狀態的情況,從而無法實現端到端的Exactly-Once語義保證。

Savepoint與Checkpoint

帶你玩轉Flink流批一體分散式實時處理引擎

checkpoint的側重點是“容錯”,即Flink作業意外失敗並重啟之後,能夠直接從早先打下的checkpoint恢復執行,且不影響作業邏輯的準確性。而savepoint的側重點是“維護”,即Flink作業需要在人工干預下手動重啟、升級、遷移或A/B測試時,先將狀態整體寫入可靠儲存,維護完畢之後再從savepoint恢復現場。

savepoint是“通過checkpoint機制”建立的,所以savepoint本質上是特殊的checkpoint。

checkpoint面向Flink Runtime本身,由Flink的各個TaskManager定時觸發快照並自動清理,一般不需要使用者干預;savepoint面向使用者,完全根據使用者的需要觸發與清理。

  • 觸發管理方式上,Checkpoint是由Flink自動觸發並管理;Savepoint由使用者手動觸發並管理
  • 主要用途上,Checkpoint在Task發生異常時快速恢復,例如網路抖動導致的超時異常;Savepoint有計劃的進行備份,例如修改程式碼,調整併發
  • 從特點上看,Checkpoint輕量,自動從故障中恢復,在作業停止後預設清除;Savepoint持久,以標準格式儲存,允許程式碼或配置發生改變,手動觸發從Savepoint的恢復。

狀態的儲存方式-MemoryStateBackend

構造方式:

MemoryStateBackend(int maxStateSize, boolean asynchronousSnapshots)

儲存方式:

- State: TaskManager記憶體;Checkpoint: JobManager記憶體。

容量限制:

單個state maxStateSize預設5M; maxStateSize<=akka.framesize ,預設10 M。·總大小不超過JobManager的記憶體

推薦使用的場景:本地測試;幾乎無狀態的作業,比如ETL。

狀態的儲存方式- FsStateBackend

構造方式:

FsStateBackend(URI checkpointDataUri ,boolean asynchronousSnapshots)

儲存方式:

State: TaskManager記憶體;

CHeckpoint:外部檔案儲存系統(本地或HDFS)。

容量限制:

·單TaskManager 上state總量不超過它的記憶體;

·總大小不超過配置的檔案系統容量。

推薦使用的場景:常規使用狀態的作業,例如分鐘級別視窗聚合、Join;需要開啟HA的作業;可以在生產場景使用。

狀態的儲存方式- RocksDBStateBackend

構造方式:

RocksDBStateBackend(URI checkpointDataUri ,boolean enableIncrementalCheckpointing)

儲存方式:

State: TaskManager上的KV資料庫(實際使用記憶體+磁碟);

CHeckpoint:外部檔案儲存系統(本地或HDFS)。

容量限制:

單TaskManager 上State總量不超過它的記憶體+磁碟;

單Key最大2G;

總大小不超過配置的檔案系統容量。

推薦使用的場景:超大狀態的作業,例如天級別視窗聚合;需要開啟HA的作業;要求不高的作業;可以在生產場景使用。

總結

本章主要講述了Flink的架構及技術原理,以及Flink程式的執行過程。重點在於Flink流處理與批處理的不同方式,從長遠來看,DataStream API應該通過有界資料流完全包含DataSet APl。

 

點選關注,第一時間瞭解華為雲新鮮技術~

相關文章