原文:https://ci.apache.org/projects/flink/flink-docs-release-1.3/concepts/programming-model.html
抽象層次
Flink為開發(fā)流式應(yīng)用和批處理應(yīng)用提供了不同層次的抽象
最底層的抽象僅僅提供有狀態(tài)的流,它通過過程函數(shù)(Process Function)被嵌入到DataStream API中。它允許用戶自由地處理來自一個(gè)或者多個(gè)流中的事務(wù),并且使用一致性容錯(cuò)狀態(tài)。此外,用戶還可以注冊事務(wù)時(shí)間和處理時(shí)間的回調(diào)來程序識別復(fù)雜的計(jì)算。
實(shí)際上,大部分的應(yīng)用程序不會用到上述描述中的底層抽象,反而會用到Core API如DataStream API(有界、無界流數(shù)據(jù))和DataSet(有界數(shù)據(jù)集)。這些流利的API提供了數(shù)據(jù)處理的通用模塊,如各種形式的轉(zhuǎn)換、連接、聚合、窗口、狀態(tài)等。這些API處理的數(shù)據(jù)類型表現(xiàn)為相應(yīng)的編程語言中的類。
底層的過程函數(shù)(Process Function)與DataStream API結(jié)合,可以去底層抽象中執(zhí)行某些特定的操作。DataSet API也為有界的數(shù)據(jù)集提供了額外的原語,如:loops/ietrations
Table API是一個(gè)圍繞表并且可能會動態(tài)改變表(表示流的時(shí)候)的聲明式DSL。Table API遵循如下關(guān)系模型:表有一個(gè)附加的模式(類似關(guān)系型數(shù)據(jù)庫中的表)并且這些API提供有可比性的操作,例如select、project、join、group-by、aggregate等。Table API程序指定了哪些邏輯操作必須做,而不是指定操作代碼的形式。雖然Table API可以通過各種用戶自定義函數(shù)來擴(kuò)展,但是相對于CoreAPI來說,還是缺乏表現(xiàn)力,但是對于用戶來說,更加簡潔了。此外,Table API會在執(zhí)行之前通過優(yōu)化器來做一些優(yōu)化操作。
由Flink提供的最高層的抽象就是SQL。這個(gè)抽象在語義和表現(xiàn)上與Table API類似,但是在語法上與SQL的查詢語法類似。SQL抽象可以與Table API進(jìn)行交互,并且SQL查詢可以在Table API定義的表上執(zhí)行。
程序與數(shù)據(jù)流
Flink程序最基本的編程模塊是streams和transformations,(注意:Flink DataSet API中用到的DataSet本質(zhì)上也是流,后續(xù)會講到)。從概念上來講stream就是一個(gè)(可能是無盡的)數(shù)據(jù)記錄流,而transformation就是將一個(gè)或者多個(gè)stream作為輸入,并產(chǎn)生一個(gè)或者多個(gè)stream作為結(jié)果的操作。
當(dāng)執(zhí)行的時(shí)候,F(xiàn)link程序就會映射成streaming dataflows(流式數(shù)據(jù)流),這些streaming dataflows(流式數(shù)據(jù)流)由stream和transformation操作組成。每個(gè)dataflow(數(shù)據(jù)流)以一個(gè)或者多個(gè)Source(源)開始,并以一個(gè)或者多個(gè)Sink(槽)為結(jié)束。Dataflow類似于有向無環(huán)圖(DAG),
通常程序中的transformation(轉(zhuǎn)換)和dataflow(數(shù)據(jù)流)中的操作都是一一對應(yīng)的,當(dāng)然,有的時(shí)候有可能一個(gè)轉(zhuǎn)換有多個(gè)轉(zhuǎn)換操作。
Sources和Sinks的文檔在streaming connectors和batch connectors的文檔中,Transformation的文檔在DataStream transformation和DataSet
transformation中。
并行數(shù)據(jù)流
Flink中的程序本質(zhì)上都是并行的分布式的。在運(yùn)行期間,每個(gè)stream都有一個(gè)或者多個(gè)stream的分區(qū),每個(gè)操作都有一個(gè)或者多個(gè)子任務(wù)。每個(gè)子任務(wù)跟其他的子任務(wù)都是獨(dú)立的,運(yùn)行在不同的線程上,并且有可能運(yùn)行在不同的機(jī)器或者容器中。
Streams可以在兩個(gè)transport之間以一對一或者重分區(qū)的模式進(jìn)行傳輸:
一對一:(如上述的Source和map之間的操作)streams保持原有的分區(qū)和元素的順序不變。也就是說map操作的子任務(wù)看到的元素的順序與Source操作產(chǎn)生的元素的順序是一致的。
重分區(qū):重分區(qū)stream(比如map和keyBy/window之間以及keyBy/window和sink之間)改變了原來stream的分區(qū)信息。每一個(gè)子任務(wù)根據(jù)選擇的信息將數(shù)據(jù)分發(fā)到不同的目標(biāo)子任務(wù)中去。
更多關(guān)于控制并發(fā)的配置請參考:https://ci.apache.org/projects/flink/flink-docs-release-1.3/dev/parallel.html
Windows
聚合類事件(如:counts、sums)在流上的處理與批處理有所不同。例如:在流上對所有的元素進(jìn)行計(jì)數(shù)是不可能的,因?yàn)榱魃系臄?shù)據(jù)是源源不斷的產(chǎn)生著。因此,流上的聚合(例如:counts、sums)以窗口作為范圍,例如計(jì)算最近5分鐘的數(shù)據(jù)量,計(jì)算最近100個(gè)元素的總和。
Windows(窗口)可以是時(shí)間驅(qū)動的(例如:每30分鐘)或者是數(shù)據(jù)驅(qū)動的(例如:每100個(gè)元素)。不同類別的窗口的典型差異:例如:tumbling
windows(翻滾窗口)(沒有重疊)、sliding windows(滑動窗口)(有重疊)以及session windows(會話窗口)(間斷的空白)。
更多Windows的例子可以從這里獲取https://flink.apache.org/news/2015/12/04/Introducing-windows.html,更多Windows的細(xì)節(jié)可以參考這里https://ci.apache.org/projects/flink/flink-docs-release-1.3/dev/windows.html
Time
當(dāng)我們提到流程序中的Time(時(shí)間)時(shí),我們先來提一下不同的時(shí)間概念:
Event Time(事件時(shí)間)是指事件創(chuàng)建時(shí)的時(shí)間。在事件中往往以時(shí)間戳作為描述,例如傳感器的連接時(shí)間、服務(wù)的產(chǎn)生時(shí)間。Flink通過timestamp assigners來獲取事件時(shí)間。
Ingestion Time(攝入時(shí)間)是指事件進(jìn)入Flink數(shù)據(jù)流源操作時(shí)的時(shí)間。
Processing Time(處理時(shí)間)是指執(zhí)行每個(gè)時(shí)間操作時(shí)的本地時(shí)間。
關(guān)于如何處理時(shí)間的詳細(xì)信息請參考:https://ci.apache.org/projects/flink/flink-docs-release-1.3/dev/event_time.html
Stateful Operations
雖然許多數(shù)據(jù)流的操作都只是一次查看一個(gè)單獨(dú)的數(shù)據(jù)流(例如一個(gè)事件解析器),一些操作則需要從多個(gè)事件中獲取信息(例如window操作)。這些操作被叫做stateful(狀態(tài)性操作)。
狀態(tài)性操作的狀態(tài)保存在一個(gè)嵌入式的key/value系統(tǒng)中,state(狀態(tài))的分區(qū)和分布與狀態(tài)性操作讀取的數(shù)據(jù)流的分區(qū)和分布是嚴(yán)格一致的。因此,只能是通過keyBy函數(shù)處理之后的有鍵值的流才能調(diào)用到key/value狀態(tài),并且僅限于與當(dāng)前的key有關(guān)聯(lián)的values。對齊流和狀態(tài)的鍵,確保所有的狀態(tài)更新都是本地操作,保證了一致性而沒有事務(wù)的開銷。這個(gè)對齊性也使得Flink能夠透明地對state進(jìn)行重分區(qū)和調(diào)整數(shù)據(jù)流的分區(qū)。
更多信息參考文檔:https://ci.apache.org/projects/flink/flink-docs-release-1.3/dev/stream/state.html
Checkpoints for Fault Tolerance
Flink通過stream的重試機(jī)制和checkpoint機(jī)制來實(shí)現(xiàn)容錯(cuò)的。Checkpoint與每一個(gè)輸入流中的特定點(diǎn)及每個(gè)運(yùn)算符中的對應(yīng)狀態(tài)相關(guān)。一個(gè)數(shù)據(jù)流可以在保持一致性的同時(shí)通過恢復(fù)檢查點(diǎn)操作的狀態(tài)和重試檢查點(diǎn)的事件來從檢查點(diǎn)鐘恢復(fù)。
Batch on Streaming
Flink執(zhí)行批處理程序是以一種特殊的流程序來實(shí)現(xiàn)的,在這種程序中流是有限的(元素個(gè)數(shù)是有限的)。DateSet在內(nèi)部被當(dāng)做流來處理。上述的概念既適用于批處理也適用于流式處理,除了一些細(xì)微的差別:
1、批處理的容錯(cuò)機(jī)制不使用checkpoint機(jī)制,當(dāng)streams重試時(shí),只能所有的一切重來。這主要是因?yàn)閿?shù)據(jù)是有限的。這種機(jī)制提高了恢復(fù)的成本,但是降低了實(shí)現(xiàn)的復(fù)雜度,因?yàn)楸苊饬薱heckpoint機(jī)制。
2、DataSet中的狀態(tài)性操作使用的是內(nèi)存數(shù)據(jù)結(jié)構(gòu)或者out-of-core數(shù)據(jù)結(jié)構(gòu),而不是key/value系統(tǒng)
3、DataSet API引進(jìn)了一種特殊的synchronized迭代,這種迭代只能在有限的數(shù)據(jù)流中使用。更多詳情,請查看iteration的文檔https://ci.apache.org/projects/flink/flink-docs-release-1.3/dev/batch/iterations.html