Trouble with Distributed Systems – Truth and Lies

前幾天講了跟分散式系統有關的網路不可靠、時鐘不可靠的鬼故事,不可靠的東西這麼多,我們要如何判斷真與假呢?在分散式系統中,我們可以陳述我們對行為所做的假設(系統模型),然後設計符合這些假設的系統,只要演算法證明相關函數正確,意味者可靠的行為正在發生,儘管底層的其他系統模型提供的保證很少也是。

這篇文章我們將會進一步了解分散式系統有關 真實 (truth) 的知識,這能幫助我們未來在設想假設時,我們的系統能提供保證到什麼程度。

多數決的真實 (The Truth Is Defined by the Majority)

只要多台節點認為你死亡,你就是死亡,儘管你是因為網路問題被丟棄你回覆的訊息,或者的 GC 跑的特別久都一樣,在分散式系統中你無法依靠單台節點來當法官,我們會用 quorum (法定人數) 來在各節點中投票,所以一般來說多數決的節點數量一定是比一半多一點,也就能容忍一些節點死亡(3 台節點能容忍 1 台死亡,5 台節點則是 2 台),我們差不多在 Day 14 談 共識算法 (consensus algorithms) 看有關 quorum 的更多 細節。

領導者和鎖 (The leader and the lock)

有些主題用英文寫出來覺得正常,但也用中文翻譯出來看起來就很奇怪- –

很多分散式系統是使用 single-leader,想像一下 leader 你吃著火鍋唱著歌,忽然就被麻匪劫了(你被 quorum 節點們宣告死亡),而你又自認為你還是 leader 時,麻煩就出來了。

像下圖 8-4 的例子,展示了不正確實現分散式 lock 機制而造成資料損壞 bug,該 storage 只有在你取得資源 lease (租約) 的時候才寫入該資源,Client 1 取得 lease 後,不幸的被 GC 暫停所有行為了,當這個暫停久到 lease 到期了,此時 Client 2 就能針對該資源取得另一份 lease ,Client 1 GC 結束返回之後,誤以為它的 lease 還是有效而繼續進行寫入,所以該資源就被污染了。

擊劍令牌 (Fencing token)

除了使用鎖和 lease 保護資源外,我們會需要 fencing 技術來保護資源被上述例子的角色所污染,如下圖 8-5,現在 Lock service 除了回覆 lease 外,會多回覆 擊劍令牌 (Fencing token),它就是個數字在每次取得 lease 時會累加,現在只要 Storage 多檢查後來寫入資源的 token 是不是比較小就可以了。

如果使用 Zookeeper 作為鎖服務,它的 zxid 或 node 版本 cversion 可以被當做 fencing token

拜占庭錯誤 (Byzantine Faults)

真實的事談完了,我們來看看什麼是假的,在分散式系統中,如果你的節點有對你說謊的風險,舉例來說就是有節點宣稱他接收到訊息了但其實沒有,這種行為被稱為 拜占庭錯誤 (Byzantine Faults) ,在這種不信任的環境中取得共識的問題也被稱為 拜占庭將軍問題 (Byzantine Generals Problem)

想了解拜占庭將軍問題,強烈建議看 李永樂老師的說明影片

本系列文的分散式系統節點們雖然不可靠,但我們都是假設它們是誠實的,因為是你或你的組織架構起分散式系統,所以本質上它們是能被信任皫,倘若你的分散系統還要支援 拜占庭容錯 (Byzantine fault-tolerant) 的話,只會徒增你系統的複雜度而已,除非你的分散式系統是跑在點對點網路上,你得面對許多不同不由你控制的節點,就像比特幣那樣。

系統模型和現實 (System Model and Reality)

很多演算法是被設計來解決分散式系統問題的,演算法要被設計成可用,就不能太依賴硬體或特定軟體來執行,反而要求我們以某種方式形式化我們期望在系統中發生的故障類型,我們通過定義系統模型來做到這一點,今天就是要用比較抽象的角度來看看這些算法能假設的事物為何。

首先是時序假設 (timing assumptions),我們有 3 個常用的模型:

  • 同步模型 (Synchronous model)
  • 同步模型假設網路延遲、程序暫停和時鐘錯誤都是有界的,意味者你會知道這些最多不會超過一個上限,但這並不符合現實生活裡的系統(網路延遲都不知道會延遲多久了)。
  • 部份同步模型 (Partially synchronous model)
  • 這個模型假設了大多數的系統行為是同步的,但它能接受有時候會有越界 (out of bound) 的事情發生。
  • 非同步模型 (Asynchronous model)
  • 這個模型的演算法不允許時序假設,它甚至沒有時鐘,所以也就沒有 timeout。

再來是節點失敗假設,一樣有 3 類:

  • 崩潰就停故障 (Crash-stop faults)
  • 演算法假設節點只能以一種方法故障,也就是節點崩潰 (crashing), 意味者節點死亡後永遠回不來了。
  • 崩潰恢復故障 (Crash-recovery faults)
  • 這個一樣假設節點會隨時故障,但它或許會在未知時間後恢復,所以它會假設節點是使用穩定的儲存設備(非揮發式硬碟),以便從故障中恢復,也會假設記憶體中的資料會消失。
  • 拜占庭式故障 (Byzantine faults)
  • 節點發瘋了的故障。

現實生活中的系統模型大多數都是 部份同步模型+ 崩潰恢復故障,那麼… 究竟分散式演算法怎麼應對這些模型呢?我們會從明天開始探討算法細節。

tshine73
tshine73
文章: 50

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *