Apache Flink 數據流編程模型

抽象等級(Levels of Abstraction)

Flink提供不一樣級別的抽象來開發流/批處理應用程序。html

Statefule Stream Processing: 是最低級別(底層)的抽象,只提供有狀態的流。它經過ProcessFunction嵌入到DataStream API之中。它使得用戶能夠自由處理來源於一個或者多個流的事件數據庫

DataStream/DataSet API: 在咱們的實際工做中,大多數的應用程序是不須要上文所描述的低級別(底層)抽象,而是相對於諸如DataStream API(有界/無界流)和DataSet API(有界數據集)的Core API進行編程。這些API提供了用於數據處理的通用模塊,如各類指定的transformations, joins, aggregations, windows, state等。在API中,這些處理的數據類型都是一個具體的實體類(class)。apache

底層的Process Function與DataStream API集成在一塊兒,能夠僅對一些操做進行底層抽象。編程

Table API: 是圍繞着table的申明性DSL,能夠被動態的改變(當其表示流時)。Table API遵循(擴展)關係模型:表有一個模式連接(相似與在關係數據庫中的表),API也提供了一些相似的操做:select, project, join, group-by, aggregate等。Table API程序申明定義了怎麼作是規範的,而不是明確指定應該是什麼樣子的。雖然Table API能夠經過各類類型的用戶定義的函數進行擴展,但它比Core API表達的更少,但使用起來更簡潔(少寫代碼)。另外,Table API程序也會經過一個優化器,在執行以前應用優化規則。windows

能夠在表和DataStream / DataSet之間進行無縫轉換,容許程序混合使用Table API和DataStream 和DataSet API。session

Flink提供的最高級抽象是SQL。 這種抽象在語義和表現力方面與Table API相似,可是將程序表示爲SQL查詢表達式。在SQL抽象與Table API緊密地相互做用,另外,SQL查詢能夠在Table API中定義的表上執行。數據結構

程序和數據流(Programs and Dataflows)

Flink能夠說是由流(streams)和轉換(transformations)爲基礎構建的(請注意,Flink的DataSet API中使用的數據集也是內部的流 )。從概念上講,流是數據記錄(多是永無止境的)流,而轉換是將一個或多個流做爲輸入,併產生一個或多個輸出流。函數

執行時,Flink程序被映射到由流和轉換運算符組成的流式數據流。每一個數據從一個或多個源(sources)開始,並在一個或者多個接收器(sinks)中結束。數據流相似於一個任意有向無環圖(DAG)。儘管經過迭代構造容許特殊形式的循環,可是爲了簡單起見,咱們姑且先忽視這種狀況。優化

程序中的轉換與數據流中的操做符一般是一一對應的。然而,有時候,一個轉換可能由多個轉換操做符組成。線程

信號源(sources)和接收器(sinks)記錄在流式鏈接器批量鏈接器文檔中。DataStream運算符DataSet轉換中記錄了轉換。

並行數據流(Parallel Dataflows)

Flink中的程序本質上是並行和分佈的。在執行過程當中,一個流有一個或者多個流分區,每一個運算符有一個或者多個子任務。操做符子任務彼此獨立,而且在不一樣的線程中執行,而且可能在不一樣的機器或容器上執行。

操做符子任務的數量是該特定操做符的並行度。流的並行性老是由生產它的操做符決定。同一個程序的不一樣運算符可能有不一樣的並行級別。

流能夠以一對一(One-to-one)或者從新分配(Redistributing)的模式在兩個操做符之間傳輸:

One-to-one: 保留了元素的分區和順序,如上圖中source —>map。這意味着map運算符的subtask[1]將按照源運算符的subtask[1]所產生順序相同。

Redistributing: 如上圖所示,map和keyBy/window之間,以及keyBy/window和Sink之間從新分配流,將會改變流的分區。每一個操做符子任務根據所選的轉換將數據發送到不一樣的目標子任務。好比 keyBy()(其經過哈希從新分區),broadcast(), or rebalance() (其隨機從新分區)。在從新分配 交換中,元素之間的排序只保存在每對發送和接收的子任務中(例如map() 的subtask[1] 和 keyBy /window的subtask [2])。因此在這個例子裏,每一個關鍵字中的排序都被保留下來,可是並行性確實形成了不一樣關鍵字彙總結果後順序的非肯定性。

有關配置和控制並行的細節能夠在並行執行的文檔中找到。

窗口(Windows)

聚合事件(如:sum,count,etc)在流上的工做方式與批處理中的不一樣。例如,咱們不可以去統計流中的全部元素,由於流通常是無限的(無界的)。於是,流中的一些aggregate操做,是由Windows控制的,例如:計算過去五分鐘或者最後100個元素的總和。

Windows能夠是由時間驅動的(例如,每30秒)或者數據驅動(例如每100個元素)。這能夠用來區分不一樣類型的Windows,例如:tumbling windows (no overlap), sliding windows (with overlap), and session windows (punctuated by a gap of inactivity).

更多的窗口示例能夠在這篇博客文章中找到。更多細節在窗口文檔

時間(Time)

當咱們在流式編程中談及時間時,能夠參考不一樣的時間概念:

Event Time, 是事件建立的時間,一般用時間戳表示。Flink經過時間戳分配器來訪問事件時間戳。

Ingestion time, 是事件進入Flink的時間,在源操做中每一個記錄都會得到源的當前時間做爲時間戳,後續基於時間的操做(如: time window)會依賴這個時間戳

Processing Time, 是指each operator 執行程序時對應的物理機的系統時間

有關如何處理時間的更多細節,請參閱event time 文檔

有狀態的操做(Stateful Operations)

儘管數據流中不少操做看起來像一個單獨的事件,可是一些操做會跨越幾個事件記下相關的的信息(好比像window operators)。這種操做被稱爲有狀態的(stateful)。

這種有狀態的操做,被保存在一種key/value的存儲結構之中。狀態與有狀態操做符讀取的流嚴格分區和分配。只有在keyed()函數以後才能訪問key/value狀態。而且僅限於與當前事件的鍵相關的值。流和狀態的keys的匹配保證了全部狀態更新都是本地操做,保證了一致性,因此不須要事務的開銷。這種匹配還容許flink從新分配狀態,並公開的調整分區。

有關更多信息,請參閱有關狀態的文檔

檢查點容錯(Checkpoints for Fault Tolerance)

Flink使用流重播(stream replay)檢查點(checkpointing) 的組合來實現容錯。檢查點與每一個輸入流中的特定點以及每一個操做元的相應狀態有關。數據流能夠從檢查點恢復,同時保持一致性(exactly-once processing語義),方法是恢復operators 的狀態並從檢查點重放事件。

檢查點間隔是在執行恢復時間(須要被重放的事件的數量)的狀況下折衷的容錯開銷手段。

容錯內部的描述提供了有關Flink如何管理檢查點和相關主題的更多信息。有關啓用和配置檢查點的詳細信息位於檢查點API文檔中。

批處理流(Batch on Streaming)

Flink執行批處理程序做爲流程序的特殊狀況,它是有限的(元素是有限的)。ADataSet 在內部視爲數據流。所以,上述概念一樣適用於批處理程序,就像適用於流式處理程序同樣,但有一點例外:

  • 批處理程序的容錯不使用檢查點。經過徹底重放流來恢復。這是可能的,由於輸入是有限的。這將成本更多推向recovery,可是使常規地處理更便宜,由於它避免了檢查點。

  • DataSet API中的有狀態操做使用簡化的內存/外核數據結構,而不是鍵/值索引。

  • DataSet API引入了特殊的同步(超級)iterations,這隻能在有界的流上進行。有關詳細信息,請查看iterations文檔

相關文章
相關標籤/搜索