flink 的核心語義和架構模型
我們在講解 flink 程式的程式設計模型之前,先來了解一下 flink 中的 streams、state、time 等核心概念和基礎語義,以及 flink 提供的不同層級的 api。
flink 核心概念
streams(流),流分為有界流和無界流。有界流指的是有固定大小,不隨時間增加而增長的資料,比如我們儲存在 hive 中的乙個表;而無界流指的是資料隨著時間增加而增長,計算狀態持續進行,比如我們消費 kafka 中的訊息,訊息持續不斷,那麼計算也會持續進行不會結束。
state(狀態),所謂的狀態指的是在進行流式計算過程中的資訊。一般用作容錯恢復和持久化,流式計算在本質上是增量計算,也就是說需要不斷地查詢過去的狀態。狀態在 flink 中有十分重要的作用,例如為了確保 exactly-once 語義需要將資料寫到狀態中;此外,狀態的持久化儲存也是集群出現 fail-over 的情況下自動重啟的前提條件。
time(時間),flink 支援了 event time、ingestion time、processing time 等多種時間語義,時間是我們在進行 flink 程式開發時判斷業務狀態是否滯後和延遲的重要依據。
api:flink 自身提供了不同級別的抽象來支援我們開發流式或者批量處理程式,由上而下可分為 sql / table api、datastream api、processfunction 三層,開發者可以根據需要選擇不同層級的 api 進行開發
flink 程式的基礎構建模組是流(streams)和轉換(transformations),每乙個資料流起始於乙個或多個 source,並終止於乙個或多個 sink。資料流類似於有向無環圖(dag)。
在分布式執行環境中,flink 提出了運算元鏈的概念,flink 將多個運算元放在乙個任務中,由同乙個執行緒執行,減少執行緒之間的切換、訊息的序列化/反序列化、資料在緩衝區的交換,減少延遲的同時提高整體的吞吐量。
官網中給出的例子如下,在並行環境下,flink 將多個 operator 的子任務鏈結在一起形成了乙個task,每個 task 都有乙個獨立的執行緒執行。
flink 集群模型和角色
在實際生產中,flink 都是以集群在執行,在執行的過程中包含了兩類程序。
jobmanager:它扮演的是集群管理者的角色,負責排程任務、協調 checkpoints、協調故障恢復、收集 job 的狀態資訊,並管理 flink 集群中的從節點 taskmanager。
taskmanager:實際負責執行計算的 worker,在其上執行 flink job 的一組 task;taskmanager 還是所在節點的管理員,它負責把該節點上的伺服器資訊比如記憶體、磁碟、任務運**況等向 jobmanager 匯報。
client:使用者在提交編寫好的 flink 工程時,會先建立乙個客戶端再進行提交,這個客戶端就是 client,client 會根據使用者傳入的引數選擇使用 yarn per job 模式、stand-alone 模式還是 yarn-session 模式將 flink 程式提交到集群。
flink 資源和資源組
在 flink 集群中,乙個 taskmanger 就是乙個 jvm 程序,並且會用獨立的執行緒來執行 task,為了控制乙個 taskmanger 能接受多少個 task,flink 提出了 task slot 的概念。
我們可以簡單的把 task slot 理解為 taskmanager 的計算資源子集。假如乙個 taskmanager 擁有 5 個 slot,那麼該 taskmanager 的計算資源會被平均分為 5 份,不同的 task 在不同的 slot 中執行,避免資源競爭。但是需要注意的是,slot 僅僅用來做記憶體的隔離,對 cpu 不起作用。那麼執行在同乙個 jvm 的 task 可以共享 tcp 連線,減少網路傳輸,在一定程度上提高了程式的執行效率,降低了資源消耗。
與此同時,flink 還允許將不能形成運算元鏈的兩個操作,比如下圖中的 flatmap 和 key&sink 放在乙個 taskslot 裡執行以達到資源共享的目的。
flink 的優勢及與其他框架的區別
flink 在誕生之初,就以它獨有的特點迅速風靡整個實時計算領域。在此之前,實時計算領域還有 spark streaming 和 storm等框架,那麼為什麼 flink 能夠脫穎而出?我們將分別在架構、容錯、語義處理等方面進行比較。
架構stom 的架構是經典的主從模式,並且強依賴 zookeeper;spark streaming 的架構是基於 spark 的,它的本質是微批處理,每個 batch 都依賴 driver,我們可以把 spark streaming 理解為時間維度上的 spark dag。
flink 也採用了經典的主從模式,dataflow graph 與 storm 形成的拓撲 topology 結構類似,flink 程式啟動後,會根據使用者的**處理成 stream graph,然後優化成為 jobgraph,jobmanager 會根據 jobgraph 生成 executiongraph。executiongraph 才是 flink 真正能執行的資料結構,當很多個 executiongraph 分布在集群中,就會形成一張網狀的拓撲結構。
容錯storm 在容錯方面只支援了 record 級別的 ack-fail,傳送出去的每一條訊息,都可以確定是被成功處理或失敗處理,因此 storm 支援至少處理一次語義。
flink 基於兩階段提交實現了精確的一次處理語義,我們將會在後面的課時中進行完整解析。
反壓(backpressure)
反壓是分布式處理系統中經常遇到的問題,當消費者速度低於生產者的速度時,則需要消費者將資訊反饋給生產者使得生產者的速度能和消費者的速度進行匹配。
stom 在處理背壓問題上簡單粗暴,當下游消費者速度跟不上生產者的速度時會直接通知生產者,生產者停止生產資料,這種方式的缺點是不能實現逐級反壓,且調優困難。設定的消費速率過小會導致集群吞吐量低下,速率過大會導致消費者 oom。
spark streaming 為了實現反壓這個功能,在原來的架構基礎上構造了乙個「速率控制器」,這個「速率控制器」會根據幾個屬性,如任務的結束時間、處理時長、處理訊息的條數等計算乙個速率。在實現控制資料的接收速率中用到了乙個經典的演算法,即「pid 演算法」。
flink 沒有使用任何複雜的機制來解決反壓問題,flink 在資料傳輸過程中使用了分布式阻塞佇列。我們知道在乙個阻塞佇列中,當佇列滿了以後傳送者會被天然阻塞住,這種阻塞功能相當於給這個阻塞佇列提供了反壓的能力。
第03講 Flink 的程式設計模型與其他框架比較
第01講 flink 的應用場景和架構模型 第02講 flink 入門程式 wordcount 和 sql 實現 第03講 flink 的程式設計模型與其他框架比較 本課時我們主要介紹 flink 的程式設計模型與其他框架比較。本課時的內容主要介紹基於 flink 的程式設計模型,包括 flink ...
程式設計與其他 一
剛剛無意看到最強大腦乙個人問另乙個人,英文本母中第18個字母是什麼,那人想了半天,扳手指頭數到第18個答出是r,但是接著問第26個字母是什麼呢,那人立刻答出 z。為什麼呢,因為大家都知道英文一共26個字母,而第26個即為最後乙個.因此我們幾乎都能立刻答出。於是我立刻聯想到這不就是資料結構中的陣列與鍊...
CString與其他型別的轉換
如何將cstring型別的變數賦給char 型別的變數 1 getbuffer函式 使用cstring getbuffer函式。char p cstring str hello p str.getbuffer str.getlength str.releasebuffer 將cstring轉換成ch...