Flink 1.7
抽象級別
Flink提供了不同的級別來開發(fā)流處理/批處理應用

最低級別的抽象提供了簡單有狀態(tài)的流。它通過Process Function嵌入到DataStreamAPI中。它允許用戶自由的處理來自一個或多個流的時間,并使用一致的容錯狀態(tài)。除此之外,用戶注冊事件時間和處理時間回調(diào),允許程序?qū)崿F(xiàn)復雜的計算。
在實踐中,大多數(shù)的應用無需在上述的低級抽象,而是針對核心API,例如,DataStreamAPI(有界/無界流)和DataSetAPI(有界數(shù)據(jù)集)的。這些流暢的API提供了用于數(shù)據(jù)處理的通用構(gòu)建塊,例如各種形式的用戶指定的轉(zhuǎn)換,連接,聚合,窗口,狀態(tài)等。在這些API中處理的數(shù)據(jù)類型在各自的編程語言中表示為類
低級Process Function與DataStream API集成在一起,因此只能對某些操作進行低級抽象。 DataSet API在有界數(shù)據(jù)集上提供了額外的基元,如循環(huán)/迭代
Table API是以表為中心的聲明性DSL,可以是動態(tài)更改表(表示流時)。 Table API遵循(擴展)關(guān)系模型:表附加了一個模式(類似于關(guān)系數(shù)據(jù)庫中的表),API提供了可比較的操作,例如select,project,join,group-by,aggregate等。表API程序以聲明方式定義應該執(zhí)行的邏輯操作,而不是準確指定操作代碼的外觀。盡管Table API可以通過各種類型的用戶定義函數(shù)進行擴展,但它的表現(xiàn)力不如Core API,但使用起來更簡潔(編寫的代碼更少)。此外,Table API程序還會通過優(yōu)化程序,在執(zhí)行之前應用優(yōu)化規(guī)則。
可以在表和DataStream / DataSet之間無縫轉(zhuǎn)換,允許程序混合Table API以及DataStream和DataSet API
Flink提供的最高級抽象是SQL。這種抽象在語義和表達方面類似于Table API,但是將程序表示為SQL查詢表達式。
SQL抽象與Table API緊密交互,SQL查詢可以在Table API中定義的表上執(zhí)行。
程序和數(shù)據(jù)流
Flink程序的基本構(gòu)建塊是流和轉(zhuǎn)換。 (請注意,F(xiàn)link的DataSet API中使用的DataSet也是內(nèi)部流 - 稍后會詳細介紹。)
從概念上講,流是(可能永無止境的)數(shù)據(jù)記錄流,而轉(zhuǎn)換是將一個或多個流作為一個或多個流的操作。
輸入,并產(chǎn)生一個或多個輸出流。
執(zhí)行時,F(xiàn)link程序映射到流數(shù)據(jù)流,由流和轉(zhuǎn)換運算符組成。每個數(shù)據(jù)流都以一個或多個源開頭,并以一個或多個接收器結(jié)束。數(shù)據(jù)流類似于任意有向無環(huán)圖(DAG)。盡管通過迭代結(jié)構(gòu)允許特殊形式的循環(huán),但為了簡單起見,我們將在大多數(shù)情況下對其進行掩飾

通常,程序中的轉(zhuǎn)換與數(shù)據(jù)流中的運算符之間存在一對一的對應關(guān)系。但是,有時一個轉(zhuǎn)換可能包含多個轉(zhuǎn)換運算符。
源流和接收器記錄在流連接器和批處理連接器文檔中。 DataStream運算符和DataSet轉(zhuǎn)換中記錄了轉(zhuǎn)換。
并行數(shù)據(jù)流
Flink中的程序本質(zhì)上是并行和分布式的。在執(zhí)行期間,流具有一個或多個流分區(qū),并且每個運算符具有一個或多個運算符子任務。運算符子任務彼此獨立,并且可以在不同的線程中執(zhí)行,并且可能在不同的機器或容器上執(zhí)行。
運算符子任務的數(shù)量是該特定運算符的并行度。流的并行性始終是其生成運算符的并行性。同一程序的不同運算符可能具有不同的并行級別

流可以以一對一(或轉(zhuǎn)發(fā))模式或以重新分發(fā)模式在兩個運營商之間傳輸數(shù)據(jù):
一對一流(例如,在上圖中的Source和map()運算符之間)保留元素的分區(qū)和排序。這意味著map()運算符的subtask [1]將看到與Source運算符的subtask [1]生成的順序相同的元素。
重新分配流(在上面的map()和keyBy / window之間,以及keyBy / window和Sink之間)重新分配流。每個運算符子任務將數(shù)據(jù)發(fā)送到不同的目標子任務,具體取決于所選的轉(zhuǎn)換。示例是keyBy()(通過散列密鑰重新分區(qū)),broadcast()或rebalance()(隨機重新分區(qū))。在重新分配交換中,元素之間的排序僅保留在每對發(fā)送和接收子任務中(例如,map()的子任務[1]和keyBy / window的子任務[2]。因此,在此示例中,保留了每個密鑰內(nèi)的排序,但并行性確實引入了關(guān)于不同密鑰的聚合結(jié)果到達接收器的順序的非確定性。
有關(guān)配置和控制并行性的詳細信息,請參閱并行執(zhí)行的文檔
窗口
聚合事件(例如,計數(shù),總和)在流上的工作方式與批處理方式不同。例如,不可能計算流中的所有元素,因為流通常是無限的(無界)。相反,流上的聚合(計數(shù),總和等)由窗口限定,例如“在最后5分鐘內(nèi)計數(shù)”或“最后100個元素的總和”。

Windows可以是時間驅(qū)動的(例如:每30秒)或數(shù)據(jù)驅(qū)動(例如:每100個元素)。人們通常區(qū)分不同類型的窗口,例如翻滾窗口(沒有重疊),滑動窗口(具有重疊)和會話窗口(由不活動間隙打斷)。
時間
當在流程序中引用時間(例如定義窗口)時,可以參考不同的時間概念:
事件時間是創(chuàng)建事件的時間。它通常由事件中的時間戳描述,例如由生產(chǎn)傳感器或生產(chǎn)服務附加。 Flink通過時間戳分配器訪問事件時間戳。
攝取時間是事件在源操作員處輸入Flink數(shù)據(jù)流的時間。
處理時間是執(zhí)行基于時間的操作的每個操作員的本地時間。
有狀態(tài)的操作
雖然數(shù)據(jù)流中的許多操作只是一次查看一個單獨的事件(例如事件解析器),但某些操作會記住多個事件(例如窗口操作符)的信息。這些操作稱為有狀態(tài)。
狀態(tài)操作的狀態(tài)保持在可以被認為是嵌入式鍵/值存儲的狀態(tài)中。狀態(tài)被分區(qū)并嚴格地與有狀態(tài)運營商讀取的流一起分發(fā)。因此,只有在keyBy()函數(shù)之后才能在鍵控流上訪問鍵/值狀態(tài),并且限制為與當前事件的鍵相關(guān)聯(lián)的值。對齊流和狀態(tài)的密鑰可確保所有狀態(tài)更新都是本地操作,從而保證一致性而無需事務開銷。此對齊還允許Flink重新分配狀態(tài)并透明地調(diào)整流分區(qū)。

容錯檢查點
Flink使用流重放和檢查點的組合實現(xiàn)容錯。檢查點與每個輸入流中的特定點以及每個操作符的對應狀態(tài)相關(guān)。通過恢復運算符的狀態(tài)并從檢查點重放事件,可以從檢查點恢復流數(shù)據(jù)流,同時保持一致性(恰好一次處理語義)。
檢查點間隔是在執(zhí)行期間用恢復時間(需要重放的事件的數(shù)量)來折衷容錯開銷的手段。
容錯內(nèi)部的描述提供了有關(guān)Flink如何管理檢查點和相關(guān)主題的更多信息。有關(guān)啟用和配置檢查點的詳細信息,請參閱檢查點API文檔。
批量流
Flink執(zhí)行批處理程序作為流程序的特殊情況,其中流是有界的(有限數(shù)量的元素)。 DataSet在內(nèi)部被視為數(shù)據(jù)流。因此,上述概念以相同的方式應用于批處理程序,并且它們適用于流程序,除了少數(shù)例外:
批處理程序的容錯不使用檢查點。通過完全重放流來進行恢復。這是可能的,因為輸入有限。這會使成本更多地用于恢復,但使常規(guī)處理更便宜,因為它避免了檢查點。
DataSet API中的有狀態(tài)操作使用簡化的內(nèi)存/核外數(shù)據(jù)結(jié)構(gòu),而不是鍵/值索引。
DataSet API引入了特殊的同步(超級步驟)迭代,這些迭代只能在有界流上進行。有關(guān)詳細信息,請查看迭代文檔。