容錯(fault tolerance)
一架噴射客機可以在飛行途中失去一具引擎,仍安全飛抵降落。這就是容錯:系統在部分零件故障時,仍能持續提供正確服務的能力。目標不是做出永不損壞的元件——那不可能——而是把它們安排成讓某個零件的故障不會變成整體的失效。一個容錯系統會吸收一個故障並繼續運作,理想上使用者完全不會察覺發生過任何事。
它怎麼建造?幾乎總是靠某種形式的冗餘:能接手或查核工作的備援資源。簡單的例子:錯誤更正碼加入冗餘位元,好讓翻轉的位元被即時更正(見 error-correcting-code);RAID 把資料分散在數顆磁碟上,於是壞一顆什麼也不會丟(見 raid);一台伺服器可以有兩個電源供應器,壞一個機器照樣運轉。一個經典方案是三重模組冗餘:三個單元算同一件事,由一個表決器取多數答案——若一個單元錯了,另外兩個會把它表決掉。每種技術都用額外的硬體、功耗或時間,換取在故障中存活的能力。
值得誠實面對它的極限。容錯處理的是你預想到的、最多某個假設數量的故障——典型是「撐過任何單一故障」。它不會讓系統刀槍不入:相關性故障(一次停電同時殺光所有冗餘電源)、複製到每份副本裡的設計臭蟲,或單純超出你預留量的故障,仍可能拖垮全局。而冗餘並不免費;為了可靠度把硬體加倍是實在的成本,所以工程師恰好容忍應用風險所值得容忍的那麼多故障——航電或銀行遠多於桌機。
三重模組冗餘:三個相同的加法器都算同一筆和,一個小小的表決電路輸出至少兩個彼此一致的那個值。若軟錯誤翻轉了某個加法器裡的一個位元,另外兩個仍一致,表決器選出正確答案,故障被遮蔽——系統其餘部分根本看不到它。
三者運算、表決器取多數:一個故障單元被表決掉,於是單一故障永遠到不了輸出。
冗餘只在故障互相獨立時才有用。一場淹水、一條共用電源,或每份副本裡同一個設計臭蟲,都可能同時拖垮所有「冗餘」零件——最昂貴的容錯失敗,來自你當作不存在的相關性故障。