1. 程式人生 > >Flink說明文件介紹---資料流程式設計模型

Flink說明文件介紹---資料流程式設計模型

文章內容是通過相應的連結地址翻譯過來的

抽象等級

程式和資料流

並行資料流

視窗

時間

有狀態的操作

針對檢查點的容錯

批處理流

下一步

Flink提供不同級別的抽象來開發流/批處理應用程式。

Programming levels of abstraction

接下來我們針對上面的每一個部分進行分析。

1、抽象等級

Stateful Stream Processing:是最低級別的抽象,它通過Process Function巢狀到DataStream API之中。它使得使用者可以自由的處理一個或多個流中的事件,同時能夠使用固定的容錯狀態。此外,使用者可以註冊回撥事件時間和處理時間,讓程式能夠實現複雜的計算。

實際上,大部分程式不需要上面描述的低級別抽象,而是使用Core APIs(核心api),比如像DataStream API(有邊界/無邊界的資料流)和DataSet API(有邊界的資料集)。這些流暢的API提供了通用的資料處理,像使用者指定的各種各樣形式的轉化,joins(連線),aggregations(聚合),windows(視窗化操作),state(狀態)等等,這些API中的資料型別在不同的程式語言中對應不同的類。低階的處理函式集成了DataStream API,這樣就可以針對特性的操作使用低層級的抽象。DataSet API 為有邊界的 data sets提供了附加的原語,例如迴圈/迭代。

Table API是一種宣告式的DSL環繞表,它可能會被動態修改(當處理資料流的時候)。Table API遵循可擴充套件的關係模型:Table有一個附加模式(類似於關係型資料庫表)並且API提供了類似的操作,如select,project,join,group-by,aggregate(合集),等等。Table API宣告式確切地定義了邏輯應該怎麼做。儘管table API是可擴充套件的通過使用者各種形式的自定義函式,它的表現還是不如Core APIs,但用起來程式碼簡潔。此外,Table API可以在執行前執行優化操作。開發人員可以毫無障礙的在table和DataStream/DataSet之間進行切換,程式中可以將Table API和DataStream和DataSet APIs混合在一起使用。

Flink提供的最高等級的抽象是sql,在語義和表達上面這個類似於Table API,只是使用SQL表示式來進行相關操作,SQL層與Table API之間進行互動,SQL的查詢在執行的時候會呼叫Table API。

2、程式和資料流

Flink程式的基本構建模組是streams(流)和transformations(轉換)。(需要注意的是,flink的dataSet API所使用的DataSets內部也是流,更多內容以後解釋)。從概念上講流(可能沒有結束)是一個數據流記錄,而轉換是一個操作,將一條或多條資料輸入,然後生產出一條或多條資料。當執行的時候,Flink程式對映到Streaming dataflows,這個由資料流和轉換操作組成。每一個dataflows開始於一個或多個source,終止於一個或多個sink。dataflows類似於有向無環圖(DAGs)。雖然迭代構造執行特定形式的環被允許,但是大多數情況下,簡單起見,我們都不考慮這一點。

A DataStream program, and its dataflow.

一般情況下,程式中的轉換和資料流中的操作是一一對應的,但有的時候一個轉換也可能由多個轉換操作組成。source和sink的文件在streaming connectors 和 batch connectors 。transformation的文件在dataStream operatorsdataSet transformation

3、並行資料流

Flink程式本質上是並行的和分散式的,在執行過程中,一個流(stream)包含一個或多個流分割槽,而每一個operator包含一個或多個operator子任務。操作子任務間彼此獨立,在不同的執行緒中執行,甚至是在不同的機器或不同的容器上。operator子任務的數量是這一特定operator的並行度。一個流的並行度是其生產operator的並行度。相同程式中的不同operator有不同級別的並行度。

流在兩個operator之間傳輸資料,可以通過一對一模式,或者通過redistributing模式:

(1) 一對一流(例如上圖中Source與map() opreator之間)保持了元素的分割槽與排序。那意味著map() operator的子任務[1]將以與Source的子任務[1]生成順序相同的順序檢視到相同的元素。

(2) Redistributing 流(如上圖中 map() 與 keyBy/window 之間,以及 keyBy/window 與 Sink 之間)則改變了流的分割槽。每一個operator子任務 根據所選擇的轉換,向不同的目標子任務傳送資料。比如 keyBy() (根據key的雜湊值重新分割槽), broadcast() ,或者 rebalance() (隨機重分割槽)。在一次 redistributing 交換中,元素間的排序只保留在每對傳送與接受子任務中(比如, map() 的子任務[1]與 keyBy/window 的子任務[2])。因此在這個例子中,每個鍵的順序被保留下來,但是並行確實引入了對於不同鍵的聚合結果到達sink的順序的不確定性。

配置和並行度的詳細配置可以檢視這個文件parallel execution

4、視窗

聚合事件(例如:計數、求和)在流上的工作方式和批處理不同。例如,對流中的所有元素進行計數是無法做到的,因為流通常是無限多的,相反,流上的聚合需要由視窗來劃定範圍,比如"針對過去5分鐘的資料進行統計"、"對最後100個元素進行求和"。

視窗可以是時間驅動的(例如:每30秒),也可以是資料驅動的(例如:每100個元素)。視窗通常被區分為不同的型別,比如滾動視窗(沒有重疊),滑動視窗(有重疊),以及會話視窗(由不活動的間隙所打斷)。

Time- and Count Windows

更多關於視窗的例子可以檢視這裡,更多關於視窗的明細檢視這裡

5、時間

當提到流程式(例如定義視窗),你可以參考不同的時間概念:

事件時間是事件建立時的時間,在事件中它通常被描述為時間戳,例如依附於生產感測器,或者生產服務。Flink通過timestamp assigners來訪問事件時間戳。

攝入時間是事件進入到Flink源操作資料流的時間。

處理時間是每一個執行時間操作的operator的本地時間。

Event Time, Ingestion Time, and Processing Time

更多如何處理時間的細節檢視這裡

6、有狀態操作

儘管資料流中的很多操作一次只檢視一個獨立的事件(比如事件解析器),有些操作卻會記錄多個事件間的資訊(比如視窗運算子),這些操作都稱為有狀態的。

有狀態操作的狀態儲存在一個可被視作嵌入式鍵/值儲存的部分中。這個狀態被嚴格地按照分割槽分散式方式與被有狀態操作讀取的流放在一起。所以我們只能在keyed streams中訪問鍵/值狀態,並且僅限於當前事件鍵相關聯的值。調整流和狀態的鍵確保所有狀態更新都是在本地操作,以保證在沒有事務開銷的情況下保持一致。這種對齊還使得Flink可以透明的重新分配狀態與調整流的分割槽。

State and Partitioning

關於更多細節,請檢視這裡

7、容錯校驗點

Flink採用stream replay(流重放)和檢查點的組合來實現容錯。檢查點與每一個輸入流及其相關的每一個運算子的狀態的特定點相關聯。一個數據流可以從一個檢查點恢復出來,其中通過恢復operator狀態並從檢查點重放事件以保持一致性 (一次處理語義)。

檢查點間隔是以恢復時間(需要重放的事件數量)來消除執行過程中容錯的開銷的一種手段

容錯內部的描述提供了更多關於flink管理檢查點和相關的話題。啟用和配置檢查點的詳細資訊請檢視這個文件checkpointing API docs

8、批量流處理

Flink將批處理程式作為流程式的特殊情況來處理,只是流是有邊界的(限定元素的個數)。一個DataSet在內部被當做是一個數據流。

上述適用於流處理程式的概念同樣適用於批處理程式,除了一些例外:

(1)、批處理程式的容錯不再使用檢查點。而是通過完全地重放流來恢復。因為輸入是有界的,因此這是可行的。這種方法使得恢復的成本增加,但是由於避免了檢查點,因而使得正常處理的開銷更小。

(2)、DataSet API中的有狀態操作使用簡化的in-memory/out-of-core資料結構,而不是鍵/值索引。

(3)、DataSet API引入了特殊的同步(superstep-base)迭代,而這種迭代僅僅能在有界流上執行。細節可以檢視迭代文件

9、下一步

我們繼續介紹分散式執行的基本概念