Chandy-Lamport分佈式快照學習記錄和Flink與實現分佈式快照的機制

Snapshot Algorithm

分佈式快照算法是拿來幹嘛的?

在缺乏全局時鐘或者全局時鐘不可靠的分佈式系統確定全局狀態

A snapshot algorithm is used to create a consistent snapshot of the global state of a distributed system. Due to the lack of globally shared memory and a global clock, this isn’t trivially possible.

Global Snapshot

全局快照我們也可以理解爲全局狀態,主要用於在Failure Recovery。

我們把分佈式系統簡化爲以節點表示的進程狀態圖,進程之間以消息隊列進行通信。

這裏的消息隊列有兩類input channel 和 output channel,channel可以看作是一個無限大的FIFO隊列。

隊列中收到的message都是有序無重複的。

C-L分佈式快照算法通過記錄每個進程的local state和input channel中有序的message作爲一個局部快照。

那麼global snapshot就是把所有進程的local snapshot全部合併起來

Chandy-Lamport

考慮一個分佈式系統,這些進程運行在不同的物理機器。一個分佈式系統全局狀態就是進程的狀態和隊列中的message

在這裏插入圖片描述

考慮一個分佈式系統,其中有兩個節點,即兩個進程再循環傳遞令牌。p和q,s0,s1對應的是兩個狀態。token可以理解爲一個令牌,全局只有一個,進程之間通過消息隊列發送令牌

s0表示進程不持有令牌,s1表示進程持有令牌。

兩個進程之間的連線代表消息隊列,token可能處於消息隊列中,這時候兩個進程狀態都是s0,都沒有令牌。

進程是有可能崩潰的
我們要保證進程崩潰重啓之後,系統仍然能夠正常運行,於是我們需要從某個檢查點恢復程序的運行狀態,這就需要定時把系統中在某個時間點的狀態保存起來,也就是做一次snapshot

保存什麼東西?

保存每個節點在當前的狀態以及消息隊列在當前的狀態(消息隊列的message)。

eg:

對上圖來說,我們對右上角的狀態做一個snapshot,保存的狀態如下:

p s0
q s0
p->q token
q->p empty

但是由於pq是兩個進程,時間不同步,例如p進程在發送token之後進行了快照存儲,q在p發送token之前進行snapshot.

1.p在snapshot的時候由於p已經發送了token,現在token在q進程隊列中,所以p進程保存快照的時候認定token既不在p也在p的接受隊列
2.q在p發送之前快照,這時候token還在p手上,因此q進程認定token不在q也不在q進程的隊列中

導致全局快照中token消失不見

解決辦法
Marker-Receiving Rule

在這裏插入圖片描述
p發送完token後發起snapshot,發送marker給q,q收到marker就保存本地狀態。由於queue是FIFO的,q先接收到token,再接收到marker,所以保存狀態的時候肯定會知道自己已經拿了token,所以記錄自己爲s1.並且p->q=empty

然後q再發送marker給p,p接收到marker,檢查p保存狀態後到接收到marker之前有沒有收到信息,由於沒有收到,所以設置q->p爲empty

這就是保存了右下角圖片的狀態。

接下來具體介紹一下CL算法的流程,主要三個部分:

1.initiate a snapshot 系統中任意一個進程發起一個snapshot
2. Propagting a snapshot 系統中其他進程逐個創建snapshot
3. Terminating a snapshot 算法結束

  • Initiating a snapshot
    1.進程Pi發起,記錄自己的進程狀態,同時產生一個標誌信息marker,marker和進程通信的message不同
    2.將marker信息通過output channel發送到其他系統的進程
    3.記錄所有從input channel接收到的message

  • Propagting a snapshot

在這裏插入圖片描述

1.進程Pj從input channel接收到marker信息
2.如果Pj還沒有記錄到自己的進程狀態,則:
Pj記錄自己的進程狀態,同時將 channel C 置爲空,並且向 output channel 發送 marker 信息
3.記錄其他 channel 在收到 marker 之前的 channel 中收到所有 message

啥意思?

比如 Pj 做完 local snapshot 之後 Ckj 中發送過來的 message 爲 [a,b,c,marker,x,y,z] 那麼 a, b, c 就是進程 Pk 做 local snapshot 前的數據,Pj 對於這部分數據需要記錄下來,比如記錄在 log 裏面。而 marker 後面 message 正常處理掉就可以了。

  • Terminating a snapshot

所有的進程都收到 marker 信息並且記錄下自己的狀態和 channel 的狀態(包含的 message)

例子:藍色表示全局snapshot

在這裏插入圖片描述
初始狀態如上:

在這裏插入圖片描述

  • P1發起全局snapshot記錄
  • P1先記錄本身的進程狀態,然後向P2發送marker信息
  • 在marker信息到達P2之前,P2向P1發送message: M

在這裏插入圖片描述

  • P2 收到 P1發送過來的marker信息之後,記錄自己的狀態。
  • 然後 P1 收到 P2 之前發送過來的 message: M。
  • 對於 P1 來說,從 P2 channel 發送過來的信息相當於是 [M, marker],由於 P1 已經做了 local snapshot,所以 P1 需要記錄 message M。
    在這裏插入圖片描述

所以我們就保持了全局snapshot的狀態
在這裏插入圖片描述

Flink 分佈式快照機制

flink通過使用分佈式快照來提供容錯服務。這些快照就充當checkpoint,系統在發生故障時候就回滾。

當某個節點宕機之後,flink將會停止分佈式數據流。然後系統會重新啓動操作算子並且將其重新設置爲最新的checkpoint.
輸入流將重置爲狀態快照記錄的位置,作爲重新啓動的並行數據流的一部分。

flink的checkpint就是基於分佈式快照實現的。

  • checkpoint 與 state

checkpoint 在flink中指的是一個執行操作,最終產生結果作爲分佈式快照提供容錯機制

state 構成checkpoint的數據構成,指的是流式計算中持久化的狀態

在這裏插入圖片描述

checkpoint執行機制

在這裏插入圖片描述

ckpoint執行流程:

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述
在這裏插入圖片描述最後Coordinator把完整的checkpoint數據存儲到checkpoint coordinator.

在這裏插入圖片描述
checkpoint執行流程

  • checkpoint僅支持flink在內部實現EXACTLY ONCE 語義,端到端的exactly once需要source 和sink的支持

但是講到這裏還是很懵

barriers是什麼鬼?

barriers

  • barriers被注入數據流並與記錄一起作爲數據流的一部分,向前流動

  • barriers永遠不會超過記錄,數據流保證嚴格有序

  • barriers把數據流中的記錄分爲當前進入快照的記錄和下一個快照的記錄

  • 每個barrier都有快照的ID,並且barrier之前的記錄都進入了該快照。

  • barrier不會中斷流的流動,非常輕量級

  • 來自不同快照的多個barrier可以同時在流中出現,也就是不同的快照可以同時進行
    在這裏插入圖片描述

  • 快照n的barrier被插入的位置是快照n所有數據最大的數據,eg: kafka最後一條記錄的偏移量。並且最後會把這個位置報告給checkpoint協調器。

  • 然後barrier向下流動,當一個算子從所有輸入流都受到快照n的barrier的時候,算子就會爲快照n發出barrier,進入到其所有輸出流中。

  • 一旦sink操作算子從其所有輸入流接收到barrier n,它就會向checkpoint協調器確認快照n完成。

  • 所有sink確認快照後,意味着快照已經完成

一旦完成快照n,job不會再去請求快照n之前的記錄,因爲這些記錄已經通過整個數據流拓撲,就是被處理結束了。

在這裏插入圖片描述

  • 一旦操作算子從輸入流接收到快照barrier n,就不能夠處理來自該流的其他任何記錄。知道從其他輸入接收到barrier n爲止 否則會搞混快照n和快照n+1的記錄

  • barrier n 所屬於的數據流暫時會被擱置,從這些流接受的記錄不會被處理,而是放入輸入緩衝區

  • 一旦從最後一個流接收到barrier n,操作算子就會發出所有掛起的向後傳送的記錄,然後再自己發出快照n的barrier

  • 之後會恢復處理所有來自輸入流的記錄,並且會優先處理來自輸入緩衝區的記錄

這就是checkpoints的對齊機制

state

當運算符包含任何形式的狀態的時候,快照也應該包含這個狀態。

狀態 state具體指的是?

1.系統狀態 :作爲運算符計算一部分的數據緩衝區,典型例子是窗口緩衝區。系統在其中收集窗口裏的記錄,直到窗口被計算或者拋棄
2.用戶定義的狀態 :可以理解爲算子map,filter等
3.操作算子在從輸入流接收到所有快照barrier的時候,以及向其輸出流發出barrier之前,會對其狀態進行寫快照。這個時候,在barrier之前的數據的狀態更新已經完成。barrier之後的數據不會更新狀態。
4.快照的狀態佔的空間很大,因此可以存儲在可配置的狀態後端,例如JobManager的內存。在生產環境下,也可以存儲在HDFS中。
5.存儲狀態之後,操作算子確認checkpoint完成,會把快照barrier發送到輸出流中,然後繼續。

異步狀態快照

上面介紹的快照過程是同步過程,當操作算子把狀態快照存儲到狀態後端的時候,會停止處理輸入的記錄。每次寫快照的時候,延遲會比較大。

我們可以把這個過程改爲異步,具體做法爲

操作算子必須能夠生成一個狀態對象,該狀態對象應以某種方式存儲,以便對操作算子狀態的進一步修改不會影響該狀態對象。copy-on-write是一種解決方法。

至於copy-on-write是什麼,請google,這裏不贅述。

輸入checkpoint的barrier之後,操作算子啓動其狀態的異步快照複製。會立刻釋放其barrier到輸出,並繼續進行常規流處理。複製過程是放在後臺完成的,它會向checkpoint協調器(JobManager)確認快照已經完成。

checkpoint僅僅在所有sink都已經收到barrier並且所有有狀態操作算子都確認完成了備份之後纔算完成。

Recovery

當失敗時,Flink選擇最新完成的checkpoint k。 然後,系統重新部署整個分佈式數據流,併爲每個操作算子重置作爲checkpoint k的一部分的快照的狀態。 數據源設置爲從位置Sk開始讀取。 例如在Apache Kafka中,這意味着告訴消費者從偏移量Sk開始讀取。

ref

snapshot
snapshot flink

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