chandy-lamport 分布式一致性快照 算法詳細介紹
在一個分布式計算系統中,為了保證數據的一致性需要對數據進行一致性快照。Flink和spark在做流失計算的時候都借鑒了chandy-lamport算法的原理,這篇文章就是對chandy-lamport算法原理的詳細介紹。
考慮一個分布式計算系統。
其中有兩個節點,也就是兩個進程,p和q,s0,s1對應的是兩個狀態。token是一個令牌,全局只有一個,進程之間互相發送令牌。s0對應的狀態就是進程不持有令牌,s1對應的狀態就是進程持有令牌。兩個進程間的連線代表消息隊列,token有可能處於消息隊列之中,這時候兩個進程都不擁有令牌,也就是都是s0狀態。這個分布式系統就這件循環地傳送令牌。
由於進程是可能崩潰的,我們需要保證在進程崩潰重啟後,系統仍然能夠正常運行,或者說我們要從某個檢查點恢復程序的運行狀態,這時就需要將系統在某個時間點的狀態保存起來。也就是說我們需要對分布式系統進行一次快照存儲,保存每個節點在當時的狀態以及每個消息隊列在當時的狀態。舉個例子,假如在上圖右上角的時刻對系統進行一個快照存儲,那麽對應的狀態就是:
p | s0 |
q | s0 |
p->q | token |
q->o | empty |
假如程序在此時崩潰了,那麽在重啟之後,就可以恢復到保存的快照狀態繼續執行。
可是由於p和q是兩個進程,時間不同步,假如p進程在發送token之後進行了快照存儲,q進程在p發送token之前進行快照存儲,那麽就會出現這種情況:
1:p進程保存快照的時候由於p進程已經發送了token,token在q進程的隊列中,所以p進程保存快照時認定token不在p進程也不在p進程的接收隊列中。
2:q進程保存快照時由於比p進程早一些,此時p進程還沒有發送token,因此q進程認定token不在q進程也不在q進程的接收隊列中。
這樣保存的全局快照裏發現token消失不見了。
為了解決這問題,chamdy-lamport算法提出了marker消息的概念:
在上圖右上角中p發送完token後發起一次快照,發送marker給q,q接收到marker消息,保存本地狀態,由於隊列FIFO,所以q接收marker消息時肯定已經接收到了token,所以q保存自己狀態為s1,保存p->q狀態為empty,然後q發送marker給p,p接收到marker,檢查在p保存狀態後有沒有收到q的消息,由於沒有收到,所以保存q->p隊列的狀態為空。到此一輪快照保存結束,全局的狀態為:
p | s0 |
q | s1 |
p->q | empty |
q->p | empty |
這個全局狀態就對應的是上圖右下角的狀態,此時全局的一致性狀態保存成功。
以上只是一個簡單的例子,實際上chandy-lamport對算法的正確性有嚴格的公式推導,感興趣可以參考https://lamport.azurewebsites.net/pubs/chandy.pdf
chandy-lamport 分布式一致性快照 算法詳細介紹