Flink分佈式執行包括調度、通信機制、檢查點

Flink的分佈式執行包括兩個重要的進程,master和worker。 執行Flink程序時,多個進程參與執行,即作業管理器(Job Manager),任務管理器(Task Manager)和作業客戶端(Job Client)。



Flink程序需要提交給Job Client。 然後,Job Client將作業提交給Job Manager。 Job Manager負責協調資源分配和作業執行。 它首先要做的是分配所需的資源。 資源分配完成後,任務將提交給相應的Task Manager。 在接收任務時,Task Manager啓動一個線程以開始執行。 執行到位時,Task Manager會繼續向Job Manager報告狀態更改。 可以有各種狀態,例如開始執行,正在進行或已完成。 作業執行完成後,結果將發送回客戶端(Job Client)。

Job管理器
master 進程(也稱爲作業管理器)協調和管理程序的執行。 他們的主要職責包括調度任務,管理檢查點,故障恢復等。
可以有多個Masters 並行運行並分擔職責。 這有助於實現高可用性。 其中一個master需要成爲leader。 如果leader 節點發生故障,master 節點(備用節點)將被選爲領導者。
作業管理器包含以下重要組件:

  • Actor system
  • Scheduler
  • Check pointing



Flink內部使用Akka actor系統在作業管理器和任務管理器之間進行通信。

【評註:上面內容對我們瞭解Flink是非常重要的,這裏與Spark對比,比如Spark通信使用的是什麼?原先使用的也是Akka,後來使用了Netty。那麼Flink是否也會改那?這個拭目以待。同時上面也是我們面試必備內容,特別是上面三者的流程圖,可以詳細說明三者之間的關係。接着我們看Akka actor 系統到底是怎麼樣的,我們接着往下看

Actor系統
Actor系統是具有各種角色的Actor的容器。 它提供諸如調度,配置,日誌記錄等服務。 它還包含一個啓動所有actor的線程池。 所有參與者都位於層次結構中。 每個新創建的actor都將分配給父級。 Actor使用消息傳遞系統相互通信。 每個actor都有自己的郵箱,從中讀取所有郵件。 如果actor是本地的,則消息通過共享內存共享,但如果actor是遠程的,則通過RPC調用傳遞消息。

每位parent 都有責任監督其children。 如果children發生任何錯誤,parent 會收到通知。 如果actor可以解決自己的問題,那麼它可以重新啓動它的子節點。 如果它無法解決問題,那麼它可以將問題反饋到自己的parent :


在Flink中,actor是具有狀態和行爲的容器。 actor的線程依次繼續處理它將在其郵箱中接收的消息。 狀態和行爲由它收到的消息決定。

【評註:關於actor其實網絡上已經有很多關於他的內容,比較難以理解的是他的父級及子級,還有郵箱我們再來看下圖】
ActorSystem模型例子:




我們來看Akka中Actor的組織是一種樹形結構,每個Actor都有父級,有可能有子級當然也可能沒有,比如樹結構中的葉子節點,每個Actor都是由其父級Actor創建,父級Actor給其分配資源,任務,並管理其的生命狀態(監管和監控),這對一個擁有成千上萬個Actor的系統來說,使用樹形機構來組織Actor是非常適合的。

郵箱是什麼鬼?
簡單來說Mailbox就是消息存儲的地方。
如下圖:


許多actors同時運行,但是一個actor只能順序地處理消息。也就是說其它actors發送了三條消息給一個actor,這個actor只能一次處理一條。所以如果你要並行處理3條消息,你需要把這條消息發給3個actors。

消息異步地傳送到actor,所以當actor正在處理消息時,新來的消息應該存儲到別的地方。Mailbox就是這些消息存儲的地方。

通過上面相信你已經懂得了actor系統


調度

Flink中的Executors 被定義爲任務slots。 每個任務管理器(Task Manager )都需要管理一個或多個任務槽(slots)。 在內部,Flink決定哪些任務需要共享slot 以及哪些任務必須放入特定slot。 它通過SlotSharingGroup和CoLocationGroup定義。

【詮釋】
我們首先來認識slot,來看下圖



TaskManager並不是最細粒度的概念,每個TaskManager像一個容器一樣,包含一個多或多個Slot。

Slot是TaskManager資源粒度的劃分,每個Slot都有自己獨立的內存。所有Slot平均分配TaskManger的內存,比如TaskManager分配給Solt的內存爲8G,兩個Slot,每個Slot的內存爲4G,四個Slot,每個Slot的內存爲2G,值得注意的是,Slot僅劃分內存,不涉及cpu的劃分。同時Slot是Flink中的任務執行器(類似Storm中Executor),每個Slot可以運行多個task,而且一個task會以單獨的線程來運行。Slot主要的好處有以下幾點:

  • 可以起到隔離內存的作用,防止多個不同job的task競爭內存。
  • Slot的個數就代表了一個Flink程序的最高並行度,簡化了性能調優的過程
  • 允許多個Task共享Slot,提升了資源利用率




共享Slot,雖然在flink中允許task共享Slot提升資源利用率,但是如果一個Slot中容納過多task反而會造成資源低下(比如極端情況下所有task都分佈在一個Slot內),在Flink中task需要按照一定規則共享Slot。共享Slot的方式有兩種,SlotShardingGroup和CoLocationGroup,這裏主要介紹一下SlotShardingGroup的用法,這種共享的基本思路就是給operator分組,同一組的不同operator的task,可以共享一個Slot。默認所有的operator屬於同一個組“default”,及所有operator的task可以共享一個Slot,可以給operator設置不同的group,防止不合理的共享。Flink在調度task分配Slot的時候有兩個重要原則:
 

  • 同一個job中,同一個group中不同operator的task可以共享一個Slot
  • Flink是按照拓撲順序從Source依次調度到Sink的




還拿上述的例子來說明Slot共享以及task調度的原理,如圖1.3假設有兩個TaskManager(TaskManager1和TaskManager2),每個TaskManager有2個Slot(Slot1和Slot2)。爲了方便理解Slot共享的流程需要提前定義operator的併發度,來決定task的調度順序。假設source/map的併發度爲2,keyBy/window/sink的併發度爲4,那麼調度的順序依次爲source/map[1] ->source/map[2] ->keyBy/window/sink[1]->keyBy/window/sink[2]->keyBy/window/sink[3]->keyBy/window/sink[4]。如圖1.3爲了便於說明流程,將source/map的併發度設爲4,keyBy/window/sink的併發度設爲4。那麼首先分配task source/map[1],這個時候Slot中還沒有task,分配到TaskManager1中,然後分配 source/map[2],根據Slot共享規則,source/map[1]和source/map[2] 屬於同一operator的不同task,所以source/map[2]不能共享Slot1,被分配到TaskManager1的Slot2,source/map[3]和source/map[4]同樣會依次分配不同的Slot,接下來分配keyBy/window/sink[1],根據Slot共享規則,它可以和source/map[1],共享同一個slot,所以也被分配到TaskManager1的Slot1中,keyBy/window/sink的其他任務依次被分配到不同Slot中。圖1.4爲並行度分別設置爲2和4的分配過程,這裏不再展開說明。



參考:https://blog.csdn.net/sxiaobei/article/details/80861070


我們明白了slot,基本明白了調度。

檢查點
Check pointing是Flink容錯的主要機制。它不斷爲分佈式數據流和executor 狀態拍攝快照。它的思想來自Chandy-Lamport算法,但已根據Flink的定製要求進行了修改。有關Chandy-Lamport算法的詳細信息,可訪問:http://research.microsoft.com/en ... ort/pubs/chandy.pdf

以下研究報告中提供了有關快照的確切實現詳細信息:分佈式數據流的輕量級異步快照(http://arxiv.org/abs/1506.08603)。

容錯機制繼續爲數據流創建輕量級快照。因此,它們可以在沒有任何重大負載的情況下繼續運行通常,數據流的狀態保持在配置的位置,例如HDFS。

如果發生任何故障,Flink將停止執行程序並重置它們並從最新的可用檢查點開始執行。

流barriers 是Flink快照的核心要素。它們被攝取到數據流中而不會影響流量。barriers 永遠不會超過記錄。他們將記錄集合分爲快照。每個barriers 都帶有唯一的ID。下圖顯示瞭如何將barriers 注入到快照的數據流中:




每個快照狀態都會報告給Flink作業管理器(Job Manager)的檢查點協調器。 在製作快照時,Flink處理記錄對齊,以避免因任何故障而重新處理相同的記錄。 這種對齊通常需要幾毫秒。 但是對於某些要求高的應用程序,即使毫秒級的延遲也是不可接受的,我們可以選擇在單個記錄處理中選擇低延遲。 默認情況下,Flink只處理每個記錄一次。 如果任何應用程序需要低延遲並且至少在一次交付就可以,我們可以關閉該觸發器。 這將跳過對齊並將改善延遲。
評註
barriers其實還是比較難以理解的,更多大家可參考
Flink實時性、容錯機制、窗口等介紹
http://www.aboutyun.com/forum.php?mod=viewthread&tid=25540


任務管理器
任務管理器是在JVM中的一個或多個線程中執行任務的工作節點。 任務執行的並行性由每個任務管理器上可用的任務槽(slot)決定。 每個任務代表分配給任務槽的一組資源。 例如,如果任務管理器有四個插槽,那麼它將爲每個插槽分配25%的內存。 可以在任務槽中運行一個或多個線程。 同一插槽中的線程共享相同的JVM。 同一JVM中的任務共享TCP連接和心跳消息:


評註
如果看懂了調度,其實這裏就好理解了。

Job客戶端
作業客戶端不是Flink程序執行的內部部分,它是執行的起點。 作業客戶端負責接受用戶的程序,然後創建數據流,然後將數據流提交給作業管理器以便進一步執行。 執行完成後,作業客戶端將結果提供給用戶。

數據流是執行計劃。 考慮一個非常簡單的字數統計程序:



當客戶端接受來自用戶的程序時,它會將其轉換爲數據流。 上述程序的數據流可能如下所示:


上圖顯示了程序如何轉換爲數據流。 Flink數據流是默認並行和分佈的。 對於並行數據處理,Flink對operators和流進行分區。  Operator 分區稱爲子任務。 流可以以一對一或重新分發的方式分發數據。

數據直接從源流向map operators ,因爲不需要對數據進行shuffle 。 但對於GroupBy操作,Flink可能需要通過鍵重新分配數據才能獲得正確的結果:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章