本節先建立處理失效(failure)所需的基本概念,接著討論失效模型(failure model),最後說明處理失效的關鍵技術——冗餘(redundancy)。

基本概念#

容錯(fault tolerance)與**可信賴系統(dependable system)**密切相關。可信賴性(dependability)涵蓋分散式系統的四項要求:

  • 可用性(availability):系統「此刻」可立即使用的機率。高可用系統在任一給定瞬間,很可能正常運作。
  • 可靠性(reliability):系統能「持續不中斷」運作的性質。與可用性不同,可靠性以時間區間而非時間點定義。
  • 安全性(safety):系統暫時失效時,不會發生災難性後果。核電廠控制、載人太空任務等程序控制系統,對此要求極高——即使只失效一瞬間,後果都可能是毀滅性的。
  • 可維護性(maintainability):失效的系統多容易修復。若失效能被自動偵測與修復,高可維護性往往也帶來高可用性;但自動復原說來容易做來難。

可用性與可靠性是兩回事:每小時停機一毫秒的系統,可用性超過 99.9999%,卻極不可靠;每年八月固定停機兩週、其餘時間從不當機的系統,可靠性很高,可用性卻只有 96%。

可信賴系統通常也要求高度的安全防護(security),尤其是完整性(integrity)議題,這留到下一章討論。

理解容錯還需要區分三個層次的詞彙:

  • 失效(failure):系統無法兌現其承諾——設計上該提供的服務有一項以上無法(完整)提供。
  • 錯誤(error):系統狀態中「可能導致失效」的部分。例如封包跨網路傳輸時,接收端把位元讀錯(1 讀成 0),甚至根本沒偵測到有東西送達。
  • 故障(fault):錯誤的成因。劣質的傳輸媒介容易造成封包損壞,這種故障好移除;但若是無線網路因惡劣天候造成傳輸錯誤,「改變天氣」就難辦得多。

建構可信賴系統的核心是控制故障,可再細分為預防(preventing)、移除(removing)與預測(forecasting)故障。對我們而言最重要的是容錯:系統即使在故障存在時仍能提供服務、繼續正常運作。

故障依持續性分為三類:

  • 暫時性(transient)故障:發生一次就消失,重試操作即可成功。例如飛鳥穿過微波發射器的波束造成掉位元,重傳多半就沒事。
  • 間歇性(intermittent)故障:出現、自行消失、又再出現,反覆不定。接頭接觸不良是典型例子。這類故障最令人頭痛——難以診斷,維修人員到場時系統往往又正常了。
  • 永久性(permanent)故障:持續存在直到故障元件被更換,例如燒毀的晶片、軟體臭蟲、磁碟磁頭損毀。

失效模型#

把分散式系統視為一群彼此通訊、也與客戶端通訊的伺服器,「服務不到位」可能出在伺服器、通訊通道,或兩者皆有。而且失常的伺服器本身未必就是故障根源——它可能依賴其他伺服器提供服務,錯誤成因得往別處找。這種相依關係在分散式系統中比比皆是:一顆故障磁碟會拖累以高可用為目標的檔案伺服器;若該檔案伺服器又是分散式資料庫的一部分,整個資料庫的正常運作都可能受牽連。

為衡量失效的嚴重程度,學界發展出多種分類(基於 Cristian 以及 Hadzilacos 與 Toueg 的方案):

  • 當機失效(crash failure):伺服器過早停止,但停止前運作完全正確;停止後就再無音訊。典型例子是作業系統整個卡死,只能重開機。
  • 遺漏失效(omission failure):伺服器未回應請求。
    • 接收遺漏(receive omission failure):伺服器根本沒收到請求——連線可能已正確建立,卻沒有執行緒在監聽。伺服器狀態不受影響,因為它根本不知道有訊息進來。
    • 傳送遺漏(send omission failure):伺服器做完了工作,卻未能送出回覆(例如傳送緩衝區溢位而伺服器沒有防備)。此時伺服器狀態已反映「服務完成」,必須準備好面對客戶端重發同一請求。
    • 其他與通訊無關的遺漏失效,可能來自無窮迴圈或記憶體管理不當等軟體錯誤,使伺服器「懸住(hang)」。
  • 時序失效(timing failure):回應落在規定的即時區間之外。回得太早,接收方緩衝區可能裝不下;更常見的是回得太慢,稱為效能失效(performance failure)
  • 回應失效(response failure):回應內容本身就是錯的,分兩種:
    • 數值失效(value failure):對請求給出錯誤答案,例如搜尋引擎系統性地回傳與所有關鍵字毫不相關的網頁。
    • 狀態轉移失效(state transition failure):對進來的請求做出非預期的反應,例如收到無法辨識的訊息時,因未做任何處置而錯誤地執行了不該啟動的預設動作。
  • 任意失效(arbitrary failure),又稱拜占庭失效(Byzantine failure):最嚴重的一類,客戶端必須做最壞打算。伺服器可能產出不該產出、卻又無法被判定為錯的輸出;更糟的是,故障伺服器甚至可能與其他伺服器惡意串通,蓄意給出錯誤答案。拜占庭失效最早由 Pease 等人與藍波特(Leslie Lamport)等人分析。

圖 8-1:不同類型的失效。

「拜占庭」一詞源自拜占庭帝國(330–1453,巴爾幹與今土耳其一帶)——傳聞其統治圈中陰謀、詭計與謊言層出不窮。這也說明了為何談可信賴系統時,安全防護同樣是重要要求。

任意失效與當機失效關係密切。前述定義下的當機是伺服器停擺最「善良」的形式,也稱 fail-stop 失效:伺服器直接停止輸出,且其他行程能偵測到它停了——最好的情況是它還先行宣告自己即將當機。現實中伺服器以遺漏或當機的形式停擺,不會這麼客氣地預告;是否已停擺得由其他行程自行判斷。在這種 fail-silent 系統裡,其他行程可能誤判——伺服器也許只是慢得出奇(表現為效能失效),並沒有死。最後,若伺服器輸出的是隨機、但其他行程一眼就能認出是垃圾的內容,這種良性的任意失效稱為 fail-safe

以冗餘遮蔽失效#

系統要容錯,最好的做法是把失效的發生遮蔽(mask)起來,不讓其他行程看見。遮蔽故障的關鍵技術是冗餘(redundancy),有三種:

  • 資訊冗餘(information redundancy):加入額外位元以便從損壞位元中復原,例如在傳輸資料附加 Hamming code 對抗線路雜訊。
  • 時間冗餘(time redundancy):一個動作做完,必要時再做一次。交易(transaction)就用這招——交易中止了重做即可,毫無損害。對暫時性與間歇性故障特別有效。
  • 實體冗餘(physical redundancy):加入額外的設備或行程,讓系統整體能承受部分元件的損失或失常。可以在硬體做,也可以在軟體做——例如多加幾個行程,即使少數行程當掉,系統仍能正確運作;換言之,複製行程即可達到高度容錯。

實體冗餘是歷史悠久的容錯手法:生物學上哺乳類有兩眼、兩耳、兩肺;波音 747 有四具引擎但三具就能飛;運動比賽設多位裁判以防有人漏看。

三模冗餘(TMR)#

實體冗餘在電子電路的應用最具啟發性。設想訊號依序通過裝置 A、B、C——任一裝置故障,最終結果多半就錯了。三模冗餘(Triple Modular Redundancy, TMR)的做法是:每個裝置複製三份,每一級之後接三個表決器(voter)。表決器有三個輸入、一個輸出:若兩個或三個輸入相同,輸出即為該值;若三個輸入全不同,輸出未定義。

圖 8-2:三模冗餘(TMR)。

  • 假設第一級的 A2 故障:每個表決器都收到兩個正確(相同)輸入與一個異常輸入,仍輸出正確值給第二級。A2 的失效被完全遮蔽,B1、B2、B3 收到的輸入與無故障時一模一樣。
  • 即使 B3 與 C1 也接連故障,其影響同樣被遮蔽,三個最終輸出依然正確。
延伸討論:為什麼每級要三個表決器,而不是一個?

乍看之下,一個表決器就能偵測並傳遞多數意見。但表決器本身也是元件,也會故障。假設表決器 V1 失常:B1 的輸入會是錯的,但只要其他部分正常,B2 與 B3 仍產出相同輸出,第二級的 V4、V5、V6 便都能把正確結果送進第三級。V1 的故障效果等同於 B1 的故障——兩種情況下 B1 都輸出錯誤值,也都會在後面被表決掉,最終結果依然正確。

並非所有容錯分散式系統都採用 TMR,但它極具一般性,清楚展示了「容錯系統」與「元件個別高度可靠、但組織方式無法容錯的系統」之間的差別。TMR 還可以遞迴套用——例如在晶片內部用 TMR 提升晶片可靠度,使用該晶片的設計者渾然不覺,甚至可能在自己的電路裡再對多顆晶片配上表決器。