嵌入式系統設計人員經常需要實現那些能在99.999%的業務時間內可靠運行的系統,這意味著一天內系統故障的時間將少于一秒。這些系統稱為高可用性系統。高可用性系統的設計通過對冗余硬件和軟件進行組合,無需人為干預即可管理故障檢測和糾錯。本文首先簡要回顧了與高可用性系統和故障管理相關的一些概念,然后研究了容錯系統的一些硬件和軟件設計模式。 故障與失效 在設計高可用性系統時,需要重點關注“故障”和“失效”。為了更好地說明,這里將“失效”定義為系統提供的業務與設計規范不符的情況。故障則是與系統相互作用的一種錯誤,它是人們通常所指的不期望發生事件的可能原因。因此,故障可能是系統的子系統失效、器件失效、外部系統失效或程序錯誤。 故障可以是瞬時故障、永久故障或周期性故障。故障一旦發生,將導致系統或子系統的狀態出錯,而這些錯誤將引發系統失效。故障處理主要有以下四種主要方法: 1. 故障預測; 2. 故障避免; 3. 故障消除; 4. 容錯。 故障預測利用數學模型和試驗提供故障及其后果的預估。例如,實際中采用的一種故障預測技術就是在系統中插入故障,研究可能出現的各種系統失效。 故障避免和消除則通過嚴格的系統、硬件和軟件開發工藝及正式規范和驗證技術加以實現。 容錯通過采用各種冗余系統實現,從而避免了故障影響。“失效弱化”是實現容錯的一種方法:即便該方法難以提供整體系統性能,也能提供切合實際的部分功能。“失效保護(fail safe)或失效即停(fail stop)”則是另一種容錯方法:當故障發生時,該方法在一個安全狀態終止系統,而不讓系統繼續執行。 容錯涉及的主要概念是冗余。容錯基于這樣的思想(或愿望):多個獨立的故障不會同時攻擊系統。容錯系統應能規避單點失效,換言之,如果系統的某部分可能出現故障,那么系統中應當存在解決該故障的冗余部分,從而避免失效。 冗余具有很多種形式: 1. 硬件冗余(低端、高端或兩者兼有); 2. 軟件冗余; 3. 時間冗余; 4. 信息冗余。 飛機內的自校驗邏輯電路及多臺飛行計算機即為典型的硬件冗余。軟件冗余可采用兩種完全不同的算法,得到的結果也完全相同。時間冗余可以利用通信重傳實現,而信息冗余則可采用備份、校驗及糾錯代碼實現。 冗余可以是動態的,也可以是靜態的,兩者均需復制系統的基本要素。在靜態冗余中,同一時刻所有的復制要素均保持激活。如果一個復制“拋出”故障,系統能夠馬上使用另一復制,并繼續正確的操作。在動態冗余中,只有一個復制保持激活,而其余復制則不激活。如果被激活的復制產生故障,先前未被激活的一個復制將被激活并接管臨界操作。 那么上述各種方法是如何實現高可用性的呢?首先,必須對高可用性進行定義。高可用性表征系統容錯并根據規范繼續提供業務的能力。系統可以采用本文給出的所有概念和方法實現高可用性。 可用性通常采用“可用度”或“每年故障時間”進行量度。常規的容錯系統可以達到99.99%的可靠度,即相當于每年故障1小時(每天故障10秒鐘)。但高可用性系統則有望實現高達99.999%的可用度,即每年故障少于5分鐘(簡單地說,即每天故障1秒鐘)。這意味著當故障出現時,系統必須能自動處理,因為操作人員難以在很短的時間內移除或掩蓋任何故障。 硬件冗余 與采用極可用器件構建單個極可用模塊的硬件設計相比,使用由常規商業級質量的器件構成的常規商業級質量硬件進行冗余復制模塊設計,無疑具有更高的成本效益。 每個復制通常都要求具有“快速失效”或“失效即停”特性,這極大地簡化了故障管理決策。每次失效都使硬件在運行中停止,而不是試圖勉強執行下去并要求管理人員指出模塊中哪些輸出發生故障,哪些則一切正常。 對于采用靜態冗余的容錯,每個復制模塊都具有常規的商用可用性。采用雙重復制的模式稱為配對或雙路復用(duplexing)。如果采用了N個復制,則稱為N路復用(N-plexing)。 圖1顯示了3路復用或3重冗余硬件設計,這三重復制均位于方框圖的底端附近。這些復制向“表決器”提交輸出,表決器決定了子系統的最終實際輸出。在N路復用設計中,當N ≥ 3時,表決器通常采用多數決策策略。但是,這需要占不失效復制的絕大多數,而不僅僅是占復制總數(失效和不失效復制)的簡單多數。 然而,表決器的硬件和軟件不是類似于系統中的任何其他模塊,也會失效嗎?實際上,確實如此;而且一旦失效,還會給系統帶來災難性的影響。但表決器通常極為簡單,因此可以通過設計和測試保證其魯棒性。此外,還可以設計復雜表決器和二級表決器等復雜系統,但本文不準備進行深入討論。 對于采用動態冗余的容錯,復制模塊仍然只需具有常規的商用可用性。一種實現方法是采用由一個被激活模塊和一個備用模塊組成的冗余對。另一方法則采用一簇模塊,這些模塊不必是其他模塊的精確復制,可以具有不同的特征、接口和容量。這簇復制需要采用失效接替策略,這樣當主模塊出現故障時,就能確定如何對多個模塊進行管理。下面給出了一些選擇: 1. 熱備用。主模塊在系統中運行時,備份模塊處于“熱備用”狀態,一旦主模塊出現故障,備份模塊將啟動并接管主模塊。例如,可以采用這種方法設計高可用性的互聯網服務器。 2. 轉動備用。主模塊在系統運行時,可以具有許多備用模塊。一旦主模塊出現故障,一個備用模塊將接管系統的運行。航天飛機上飛行計算機的設計就基于該原理:主模塊由兩臺總穩定工作的計算機組成,其中一個備用模塊是一個相似對(similar pair),而第二個備用模塊則是一臺只能根據操作員指令接管系統的計算機。 3. 非關鍵模塊的失效接替。主模塊占用系統的關鍵資源,備用模塊則占用其他非關鍵資源。一旦主模塊出現故障,備用模塊就能接管主模塊占用的大部分關鍵資源。日常生活中我們也常常這么做:當我們試圖發送一封緊急的電子郵件時,如果計算機的高速互聯網連接出現故障,我們會立即切換到舊式的調制解調器。 4. 共同接管。每個模塊均運行自帶的關鍵資源,而且一旦某個模塊發生故障,其他模塊還能接管故障模塊的關鍵資源。例如,在功能增強的心護理室中,每8位病人將設置一臺心臟監控計算機。如果一臺心臟監控計算機崩潰,那么鄰近的計算機也能對故障計算機監控的8位病人進行監控(或許性能將有所降低)。 正確的失效接替實現非常關鍵。如果故障的主模塊需要拋棄故障并繼續執行,而同時另一模塊也試圖接管其業務,那么后果將是災難性的,因為它們的業務有可能產生沖突。如果主模塊拋棄故障后停止執行,而又沒有其他模塊接管其業務,這樣的后果同樣是災難性的。因此失效接替的驗證和測試非常關鍵,盡管我們當中的許多人并不熱衷于此。 軟件冗余 大多數硬件故障都是隨機產生并由物理缺陷導致,這些缺陷要么在生產過程中維持不變,要么隨器件的老化而不斷變化,要么將受到外部物理環境的沖擊。相反,軟件故障與物理條件無關,因為軟件不會老化。與硬件故障不同,軟件故障源自對軟件設計或實現中固有故障的軟件路徑調用。由于軟件通常比硬件復雜,因此軟件中可能具有比硬件多得多的內置缺陷,從而導致軟件中的故障更多,容錯設計的成本也更高。 N版編程(N-version programming )是久經考驗的一種軟件容錯設計方法。20世紀70年代偶然接觸到該方法時,那時還被稱為異質軟件(dissimilar software)。這是硬件N路復用(如圖1所示)的等價軟件實現。但該方法比硬件N路復用的復制機制復雜,N路復用中相同軟件的N個復制將包含相同的故障并產生N次相同的錯誤。在N版編程中,如果N套軟件功能需要并行運行,那么它們應當是該功能的N個不同實現,而且是由N個單獨的開發團隊獨立開發完成。這就是N版編程的基本原理。 1996年6月,當首次發射的阿麗安娜-5衛星發送火箭上升到4000米高空時,突然發生了爆炸。該事故的原因在于火箭的慣性參考系統(這是數字飛行控制的一部分)發生了故障。盡管慣性參考系統中引入了硬件冗余,但軟件冗余沒有得到正確的處理。阿麗安娜-5帶有兩臺慣性參考計算機,一臺處于工作狀態,而另一臺則處于“開機”備用狀態。這兩套系統并行運行,并具有完全一樣的硬件和軟件。系統上的軟件也與先前已經成功發射的阿麗安娜-4幾乎一模一樣,但由于阿麗安娜-5上的某些飛行參數值比阿麗安娜-4大,因此數據發生了溢出。解決問題的方法是關閉計算機,由于冗余計算機也在運行相同的軟件,因此也將受到數據溢出的沖擊,從而很快關閉,這樣整個慣性參考系統就完全崩潰。結果,引擎的噴管被回旋至極限位置,導致火箭突然轉向,并在自毀之前裂成兩半。這種處理數據溢出錯誤的方法適用于處理隨機出現的硬件錯誤,但不適用于處理兩臺計算機上出現的類似軟件錯誤。N版編程可以避免兩臺計算機出現類似的軟件錯誤。 在20世紀70年代,N版編程(N-version programming)是先進的軟件容錯設計方法。此后,這種設計模式引發了一系列問題:隨著該技術的采用,軟件開發成本直線飆升,因為必須成立N個單獨的團隊開發N套相互獨立的軟件。如果期望降低成本,則將陷入所謂的“平均智商( Average IQ)”怪圈:較低成本的開發團隊意味著較低質量的軟件工程師,而這些工程師只能開發出較低質量的代碼。因此,最終只能得到充斥著以N種不同方式產生故障的N種不同程序。 N版編程面臨的另一個問題在于如何為N個獨立開發團隊提供輸入。一般情況下,將為所有的N個開發團隊提供相同的規范標準。然而,一旦規范存在缺陷,那么將得到N個獨立開發的包含類似軟件故障的版本。如果系統發布之后,規范或使用錯誤得到識別,那么每個新錯誤都需要糾正N次,即N個不同的實現都需要加以糾正,這樣維護成本就相當驚人。現在,最佳的N版編程方法是讓第一流的軟件開發團隊,利用最可靠的底層架構、軟件開發工具、技術和測試來開發出高質量的軟件版本。 校驗點恢復 與基于靜態冗余的N版編程不同,許多軟件容錯設計模式均基于動態冗余。這些設計模式均包含以下四個步驟: 1. 故障檢測 2. 損害評估與 限制(有時也稱為“防火墻處理”) 3. 故障恢復 4. 故障處理和業務繼續 步驟二中,當檢測到軟件錯誤時,一般可以采用失效保護。但軟件往往極其復雜,因此消除故障軟件導致的后果也并非輕而易舉。事務的概念是解決該問題的一個有效工具,事務是應用狀態下操作的集合,這樣事務的起始點和結束點均是應用的穩定狀態。例如,每個城市的市政廳都具有一個包含該城市所有居民信息的文件系統。當一對夫妻結婚時,他們的姓名和結婚日期都記錄在一個命名為“已婚夫妻”的文件中。另外,記載新郎從單身到已婚狀態變化的文件稱為“男性居民”;記載新娘從單身到已婚狀態變化的文件稱為“女性居民”。如果上述3個文件中的一個未能得到有效更新或者軟件在更新過程中突然崩潰,我們將不得不返回到該婚姻“事務”的起始點。否則,將只會以不穩定狀態而告終,如新郎顯示為已婚狀態,而新娘則仍然顯示為單身狀態。穩定狀態只出現在婚姻事務的起始點以及得到成功處理的結束點。 如果希望在容錯中引入事務概念,系統必須能在事務的起始點保存系統狀態,這稱為檢驗指示。檢驗指示需要在開始新事務之前迅速保存系統狀態,并且必須要求先前的事務以無差錯狀態結束。這里,一種基本的恢復策略是再執行方法:一旦事務中檢測到錯誤,事務將進行失效保護,系統將重新載入最近保存的檢驗點。這樣業務又能從檢驗點繼續執行下去,并允許在該穩定狀態上進行新的事務處理。然而,這樣將丟失進行失效保護的事務。這類故障恢復也稱為后向故障恢復,因為軟件狀態將還原到先前的一個無差錯點上。 簡單的檢驗指示本身也容易引發單點失效,因為在保存檢驗點狀態時有可能出現故障,但我們可以采用一種稱為檢驗點還原(checkpoint-rollback)的方法解決這個問題,如圖2所示。圖中,橢圓符號代表通過發送隊列消息進行通信的軟件客戶和軟件服務器。一個事務可以包含許多從客戶機發往服務器的請求消息以及從服務器發往客戶機的響應消息。在一個事務中,數據在服務器中修改。在事務的結束點,右圖所示的兩個恒定大容量存儲設備將記錄穩定的數據集和事務序列號。如果某一時刻檢測到錯誤,而服務器已被關閉,那么服務器將重啟(或啟動備用服務器)。作為啟動恢復過程的一部分,兩個大容量存儲設備還需要檢驗事務序列號。服務器數據將根據包含最高序列號的設備進行恢復。因為故障出現在設備檢驗中,因此另一大容量設備將帶有較低的序列號。 流程對設計模式 檢驗點設計模式的一個缺陷在于故障恢復時間過長。啟動或重啟服務器需要進行許多處理,才能恢復到檢驗點狀態。“熱備用”服務器與其自帶的恒定大容量存儲設備的直接協同工作可以加速恢復,該設計模式也稱為流程對(process pair)設計,如圖3所示。 圖3中,方框圖中央是一個工作原理與先前檢驗點情形非常相似的主服務器,客戶機直接與主服務器協同工作。一旦主服務器成功地完成整個事務,將傳送與新的穩定狀態相關的信息至備用服務器(右端的服務器)。主服務器和備用服務器都將在恒定大容量設備中記錄數據。這樣,備用服務器就能保存完整事務的當前信息。當主服務器準備就緒并可供客戶機使用,將向備用服務器發送常規的“心跳消息(heartbeat message)”,這些心跳消息還可以同某些檢驗點消息相結合。一旦檢測到心跳消息流終止,備用服務器就知道主服務器已關閉或無法使用,進而作為一個新的主服務器迅速接管事務。 該設計模式不僅適用于客戶機、主服務器和備用服務器均位于同一處理器或模塊上的情形,還適用于三者位于不同處理器或模塊的情形。 盡管流程對設計模式具有諸多優勢,但仍有一些問題需要解決。例如,備用服務器丟失了檢驗點消息或消息的順序不對,而且,當主服務器是物理設備的控制器并在操作中發生故障時,也會產生問題。當備用服務器接管事務時,不必知道如何完成操作,因為備用服務器并不知道主服務器失效之前究竟運行到哪一步。 需要再次重申的是,在流程對設計模式中,當主服務器失效時,仍在進行的事務將在執行中丟失或撤銷。備份服務器接管主服務器的狀態是主服務器失效前報告給備用服務器最后完成的事務的狀態。 恢復程序塊 動態軟件冗余的另一種設計模式稱為恢復程序塊。該方法基于檢驗指示,但添加了對軟件處理結果的驗收測試。設計中必須準備數據處理的替代方法(就像在N版編程中一樣),但不必對每個事務運行所有的數據處理方法。相反,可以選擇一種數據處理方式作為主方式,并且首先只采用主方式處理事務。一旦主處理完成,即可運行驗收測試。如果驗收測試通過,則表明主數據處理方式完全有效。如果驗收測試失敗,則可如圖4所示,繼續試驗下一個替代方案。 如方框圖所示,必須在首次進入恢復程序塊之前進行檢驗指示。每次失效的驗收測試之后,軟件必須還原到檢驗點狀態。每次嘗試替代的處理方法之后,都必須進行驗收測試。這樣,需要不斷進行處理方式更迭,直到提供通過驗收測試的處理方式。這些“良好”的輸出構成了恢復程序塊的最終結果。 前向故障恢復 檢驗點恢復、流程對和恢復程序塊都是后向故障恢復方法。大多數動態軟件容錯都采用后向故障恢復方法,但前向故障恢復也是不錯的選擇。前向故障恢復的基本思想是從錯誤狀態繼續進行并通過校正清除故障。前向故障恢復基于精確的錯誤損失評估,因此通常取決于具體的系統。異常處理就是前向故障恢復的一個典型例子,當檢測到問題,該方法就發送命令至專用的異常處理軟件,而不是返回到先前某個檢驗點狀態并繼續執行下去。 替代處理是前向故障恢復的一種設計模式。當某個事務存在兩種(或更多)處理選擇時,就可以采用替代處理方法。在這兩種處理方法中,一種方法非常精確,但計算復雜;另一種方法則相對簡單并具有更高的性能。替代方法不僅可用作測試,而且當主處理方法出現故障時也可用作二級結果提供器。例如,平方根算法可作為主處理方法,而表查詢插入算法則可作為替代方法。一旦運行了平方根算法,表查詢插入算法不僅可用于測試平方根算法所得結果的質量,還能迅速校正這些結果中的錯誤。 圖5中,為了控制飛機(波音777),同時采用了兩套數字飛行數字系統。框圖右側的決策邏輯電路將簡單飛行控制系統的輸出作為測試復雜的主飛行控制系統輸出的衡量標準。如果驗收測試失效,簡單飛行控制系統的輸出也可用作失效主輸出的替代,向左的箭頭表示替代處理的結果也可為主處理提供反饋。 上述設計模式使采用常規商業級質量的硬件和軟件為真正的高可用性系統構造程序塊成為可能,這樣的高性能系統無需人為干預,即可實現高達99.999%或更高的可靠性。 |