High Availability啟示錄
來自: http://yq.aliyun.com/articles/5555
文/秣馬
最近對HA(High Availability,以下簡稱HA)有些感想,在此以一個理工男的視角將其記錄下來,希望能以饗讀者。
很多年以前,HA是個高大上的東西,只有一些大公司或關鍵業務才會使用。隨著技術的演進,HA已變成了現代網絡服務的必備。
相信很多人一定了解HA的基本原理,但似乎也講不出道道來,那就可以繼續讀下去。如果看官你對HA已經很精通了,那可直接跳到后記看啟示錄。
在探討HA之前需要搞清下面幾個概念或術語。
術語
RAS
RAS是三個詞的縮寫,即:
-
可靠性(Reliability)
-
可用性(Availability)
-
可服務性(Serviceability/Maintainability)
RAS起源于IBM對其主機質量的定義。詳細定義可以參考wiki詞條:http://en.wikipedia.org/wiki/Reliability,_availability_and_serviceability_(computing))。可靠性用來定義指定時間內系統可靠程度,用MTBF(即平均故障間隔時間)來度量,MTBF表示平均無故障間隔時間,是指兩次故障修復之間的平均時間。
介紹可用性之前先看幾個相關度量:
MTTF, MTTR
MTTF(mean-time-to-failure) 為平均無故障時間,即系統正常運行的時間。
MTTR(mean-time-to-repair) 為平均故障恢復時間,即系統修復故障的平均時間。
MTBF = MTTF + MTTR,對不能修復的故障用MTTF,對可修復的故障用MTBF,由于MTTR都遠小于MTTF,所以MTBF約等于MTTF。
可用性定義為: MTTF/(MTTF+MTTR)
可用性用來描述系統在指定時間內可以正常工作的時間比例,通常用幾個9來表示,如下圖所示:
一般來說,HA就是指5個9,要做到6個9及以上的要求,所花費的代價會大幅增長。
可服務性用來描述系統出問題時被修復的速度。由于這個時間會影響可用性,所以越快修復則系統可用性越大。
可靠性和可用性在字面上理解感覺很相似,但是有區別的,可靠性一般與安全有關,可用性一般與用戶體驗有關。系統或許是可用的,但并不一定是可靠的。舉例來說,一個系統可能從不宕機,但運行時數據經常發生損壞。
不同系統對二者要求是不同的,例如對那些航空航天產品,可靠性要求就很高,可用性肯定次之,相反對于手機等民用產品可用性要求就比可靠性高些,飛機不可靠的話,道理你懂的。可靠性的增加會顯著增加費用,如果手機做成象飛機那么可靠,費用就不是一般高了, 用戶肯定也接受不了,再說也沒有必要,大不了換個手機,而手機可用性不好會更影響用戶情緒。
現在RAS概念被用來評估一個系統,或一個軟件層面,單純強調一個特性沒有意義。一個實際的系統應該根據應用場景在RAS和成本方面進行折中。
HA
HA即 High Availability,顧名思義是高可用性。相應詞條可見wiki: http://en.wikipedia.org/wiki/High_availability
HA是一個系統層面的概念,不是指單個節點。
HA只是一個指標,即達到幾個9以上才能稱為高可用性,并沒有規定具體系統的實現模板,細節等,但我這篇文章不只是談HA這個指標,而是從概念,層次等各個方面來闡述HA系統。
這里高可用性中的“高”是個相對概念,既然有高,那也應該有低可用性,很高可用性,極高可用性,有專家將這些等級做了個劃分,如下圖所示:
需要指出的是,目前HA一般指5個9,但這里的級別也是隨著技術進步,軟/硬件穩定性提高不斷提高的,在未來或許5個9以上都是標配了。
既然有HA,那肯定也有HR(High Reliability),即高可靠性,在涉及安全的領域也有很多相關標準,我這里不打算詳細介紹(主要是沒深入研究),只提幾點:
-
串行部件組成的系統的可靠性是由可靠性最低的部件決定的。
-
并行部件組成的系統的可靠性是所有部件的可靠性乘積。
-
系統的可靠性是可以通過子系統的冗余來提高。
-
軟件的可靠性是可以通過加強測試來提高。
-
硬件的可靠性的提高會顯著提高成本。
在現實生活中,HA系統也是比比皆是,比如有4個引擎發動機的大型飛機,就是一個HA系統,一個發動機壞了也不至于飛機失去動力而墜毀。當前各種分布式計算架構,存儲架構也都是HA系統,包括我們人自身更是一個復雜的HA系統,單個細胞可以隨便死去,我們人體可以生成新細胞來替換老細胞。
所以HA系統的主要思想是通過對不可靠的單節點冗余來換取整體系統的穩定可用。
世界本是虛實之間,虛的東西比如理想,比如精神都是很完美的,無故障,無錯誤的,實的東西就剛好相反,不完美,不可靠,有很多問題。針對于HA的節點來說也是一樣不完美,不可靠,HA的意義就在于通過運行一套擁有冗余節點的系統,來對抗單個節點的不可靠,對外提供一個看起來比較完美的虛的接口,從而來提高整個系統的可靠性,可用性和可服務性(或叫可維護性)。
不要說你發明了HA系統,這些都是大自然給我們的提示,也不要說你發現了HA系統,你有沒有發現,它都在那里,不增不減。我們所做的都是在模仿大自然杰作而已。
HA三原則
-
消除單節點故障
-
互聯可靠
-
故障檢測
一個HA系統必須滿足上面三個基本原則,否則就不可能被稱為一個HA系統。
第一條,消除單節點故障是指,系統必須提供節點冗余,這也意味做單節點不可能是HA系統。
第二條,互聯可靠是指,節點之間,節點和外界之間的連接必須是可靠的,這些連接本身不能存在單點故障。
第三條,故障檢測是指,系統必須能夠檢測到節點的故障,從而做出必要處理。
Fault Tolerance
Fault Tolerance系統是指系統在處理故障方面的能力程度。從系統層面來說,HA系統就是一個Fault Tolerance系統,但Fault Tolerance系統則不一定是一個HA系統,因為它更強調的是系統對故障的預估及處理能力。比如一個正在運行的進程,正常運行沒有問題,但可能會遇到很多意外事件,比如磁盤滿,網絡斷,用戶輸入buffer越界等,如果沒有預估到這些事件,則可能會導致故障,那么這個程序就不是一個Fault Folerance很好的程序。
另外Fault Tolerance系統早期常多用于硬件設計,我們這篇文章主要是探討現代網絡服務系統多著眼于系統。
Fault Tolerance字面可譯作故障容忍,可以說其HA系統成敗之關鍵,鑒于其重要性,早在1985年,IEEE的IFIP專家組就對Fault Tolerance做了深入研究,這些專家們就“Dependable Computing and Fault Tolerance”提出了一系列概念,這些概念不斷演進和擴充,如今便有了下面這些所謂概念框架:
這些專家將Fault Tolerance概念整體納入可信賴計算(Dependable Computing)范疇,并從三個角度來定義/度量可信賴計算,這三個角度分別是:
-
可信賴計算面臨的威脅
這些威脅可進一步定義為:缺陷(fault),錯誤(error),故障(failure,我覺得翻譯成故障比失敗更貼近中文一點)
這些概念就是這樣一環套一環的: 缺陷 --> 錯誤 --> 故障
這些東東放到下面這個圖中就比較容易理解了:
圖中可以看出,當一個缺陷導致了錯誤,這個錯誤又導致故障發生,從而中斷了正常的服務狀態,而這個故障經過了一個延時后又被檢測到了,并被修復了,最后服務又回到正常狀態。
-
缺陷比較好理解,就是模塊,部件,人員等本身的問題,或由這些導致的問題,例如硬件缺陷,設計缺陷,人工操作,環境問題。
-
錯誤難理解一點,錯誤被定義為上述缺陷導致的結果,是系統的一個狀態。比如軟件中有個野指針,這是一個缺陷,如果用這個野指針訪問了一個內存便會導致一個錯誤。
-
故障被定義為錯誤導致的結果,接上面例子,如果有個野指針訪問了某個內存,而又沒有通過異常處理機制捕獲,則程序會出錯導致非正常退出,這個錯誤最后造成一個軟件服務故障。當然如果你能在其他模塊中檢測到這個故障,并且能夠修理就是一個基本的Fault Tolerance系統了。
構建可信賴計算的方法
故障可以通過兩種方法來消除,這兩種方法分別是: 構建(Contruction,之前也被稱為Procurement), 驗證(Validation)。這兩種方法也分別對應于模塊/組件的兩個階段:
-
構建對應于模塊/組件的構建階段,在這個階段又可以通過兩種方法來處理故障,即故障避免(Fault avoidance)和故障容忍(Fault tolerance)。前者比較好理解,就是在軟/硬件實現階段將各種故障原因都考慮進去,并進行規避。后者則涉及到軟/硬件的兼容性問題,比如后續版本對以前版本的兼容就可以避免此類故障。
-
驗證對應于模塊/組件的運行階段,在這個階段可以做的事件有兩種,第一種是故障消除(Fault Removal),即出了問題后怎樣想辦法消除它,基本上屬于事后補救。第二種是故障預測(Fault forecasting),即將故障扼殺在搖籃中,基本上屬于事前預防。
可信賴計算的的屬性
IFIP專家最早只提到兩個屬性,即Availability和Reliability,但到現在為止已經擴充到6種屬性,即:
可以看出,這些屬性已經覆蓋了之前提的RAS,這些屬性都有相應公式進行度量,我在此就不展開了,有興趣的可以谷哥或度娘。搞懂后就可以出去Zhuangbility了。
-
Availability
-
Reliability
-
Safety
-
Confidentiality
-
Integrity
-
Maintainability
以上提到概念的只是可信賴計算概念的一小部分,也是很基礎的一部分,里面還有很多門道,這里拋個磚,有興趣的可以進一步學習,拋塊玉給我。
解釋了這么多Fault Tolerance,可以看出專家與普通人的區別了吧:能對我們都知道的東西歸個類,下個定義,用公式描述一下就是專家,否則就是路人甲。呵呵,只是逗比一下,專家也是真心不那么容易的,想象一下著名的CAP理論不也是在三個詞之間玩文字游戲么?你心里就會說,why didn't I think of that? 就是啊,why? 因為你還沒有打通任督二脈,還不是專家嘛。
Failover
Failover字面意思是失效轉移,這是HA的一項簡單的容錯功能,在早期簡單的HA系統一般是AS(A: Active,S: Slave)雙節點結構,即一主一備,兩個節點之間通過一個串口或網線作為心跳線互相連接,平時只有Active節點工作,心跳斷了后,主節點不管正不正常,都自動關閉,備份節點自動接管,并且升級為主節點,從而保持系統正常運行。當失效節點修好重新集成進來后,仍然保持為從節點。這樣的切換過程被稱為Failover。
當然也有AA模式的雙節點結構,這種情況下兩個節點都可以同時工作,并且還可以做load Balance,但一般都用在輕量級狀態同步,Failover系統主要是以容錯功能為主。
LB
LB是Load Balance,即負載均衡。這個其實HA系統的一個性能方面擴充,有些系統沒有LB功能,但仍然可以做到5個9。LB的作用主要是提高系統的性能,LB本身也是一個值得大費筆墨的東西,這里先不展開,后面會闡述各種HA + LB的模式。
HA系統組成
前面說了,HA系統種類很多,比如硬件類,像處理器HA,物理網絡鏡像,RAID0,cluster computing等等,實現形式也各不相同,這里我只討論網絡服務的HA系統(后面所說的HA系統都是指網絡服務HA系統),并總結一下其基本組件及各種實現模式。
現代HA系統幾乎都有LB功能,一個重要原因是單個模塊的可靠性相比以前有很大提高,如果僅做為備份則是很大的浪費。
為了更好的描述HA系統,我畫了一個2節點的HA網絡服務架構圖:
圖中可以看出,每個節點都有通信模塊,控制模塊,狀態管理模塊。而每個節點的同樣模塊構成了HA系統的一個層,按照功能,HA系統可以簡單的分為四個層:
-
節點層
-
網絡層
-
控制層
-
業務層
節點層是一個獨立的節點,可以是物理節點,比如一個PC,也可以是邏輯節點,比如一個進程。但從HA實施來說,最好是物理上獨立的節點,這樣不會產生依賴,從而導致單點故障。
網絡層主要實現對外的虛接口,比如VIP。同時完成節點之間通信。很多現代的HA網絡服務不單會提供HA服務,同時也兼顧性能,一般是HA + LB的混合體,即在HA基礎之上會提供LB功能,LB功能一般是在HA組件的網絡層提供,在實現方式上可能會有一個單獨模塊來進行流量調度,也可能是由節點之間互相協調流量調度,后面會對這部分詳細介紹。
控制層主要實現節點狀態探測,失效接管,集成等功能,即Fault Tolerance。
業務層主要是維護業務方面的狀態一致性,業務狀態是指節點上運行的服務本身的狀態,這部份狀態只跟這個節點上運行的服務相關,跟其他節點沒有關系,即具有局部性,就像是個局部變量一樣。業務層需要維護所有節點的業務狀態的一致性,以便當某節點失效時,其他節點能從這個失效時的狀態開始順利的接管業務。這個如果節點沒有業務狀態,則這層可以不用實現。
HA分層
上面提到HA系統一般會分為四層,但根據實際情況,有些層可能不需要或者會大幅簡化,比如,如果是無狀態系統,則業務層基本上就只需要關注自身業務就可以了。
同時每個層的部署位置也可能不盡相同,比如,有些系統的業務層中的狀態可能會下沉到一個獨立的系統里,而不是分布在每個節點上,例如一些數據庫系統可能將數據庫放在SAN網絡上,這樣每個節點就不需要業務狀態維護了。
還有些系統需要更好的性能,可能會單獨設立一個流量調度單元來完成。再比如,有些系統的控制層會將大部分邏輯放到另外一個子HA系統進行處理,而各節點的控制層作為客戶端來與這個子HA系統進行交互。
節點層
節點是HA服務的容器,HA服務對外是虛擬的,但最終會在某個節點上落地。節點必須為運行該服務提供合適的環境。
節點之間是物理獨立的,獨立的目的就是要提供物理層面的冗余。上面說過了,節點也可以虛擬節點,比如在同一物理機上運行多個VM,然后在這些VM中運行服務,那么這些VM就是虛擬節點。但由于這些VM共同運行在一個物理機上,物理機down掉后所有這些VM節點會一起down,這樣就違背了HA的第一條原則,即節點之間不存在單點故障。所以如果虛擬節點之間存在共同依賴關系時,這樣就不可能成為一個完備的HA系統。但如果這些VM都運行在不同的物理機上時,便沒有依賴關系,這樣的HA系統便是完備的。
此外節點之間的網絡互聯也是必須要考慮的,這里的互聯是指物理層,包括邏輯層的互聯。我將其劃歸節點層的目的是,這層是提供物理上的冗余,單個節點的冗余還不夠,網絡層面也必須有多路徑冗余。
網絡層
這里網絡層是指軟件層面的網絡服務。網絡層主要有如下責任:
-
實現虛接口
-
節點通訊
-
流量調度
虛接口
虛接口是HA系統非常重要的組成部分,虛接口主要作用是向外部提供一個訪問接口,從而將內部實現與外部環境分隔開來,避免暴露內部實現細節,這也是軟件設計的一個基本原則。其實現方式可以直接決定HA系統可用性。
從概念上講,接口一般是數據流集中匯聚之地,如果為HA設計一個集中的接口來轉發外部請求,對軟件設計來說是很方便的,貌似也可以。但別忘了,這種設計與HA系統基本原則相矛盾,如果這個接口掛掉了,那么整個HA系統就崩潰了,所以這種設計就不能稱為HA系統,即使后端的處理節點可能是物理獨立的。所以這里之所以稱其為虛接口,就是因為對外部來說,用戶訪問的邏輯形式是集中的,但在內部實現時卻是分散的,即最后實現時會在某個具體節點上落地。這樣的虛接口才能滿足HA系統要求。
常見的虛接口形式有VIP(virtual ip), DNS, RPC,虛擬網絡文件系統等。具體采用哪種形式應根據業務需求。現實實現時,由于有些功能是所有節點共有的,所以有時也會將這個虛接口單獨作為一層來處理,此時,這層本身也可以是一個HA系統,所有外部請求將由這層來轉發到實際處理的節點。例如lvs,分布式文件系統的meta節點等。
VIP
VIP是一種很常見的虛接口,在針對ip服務時幾乎是標配,實現方式也有多種:
-
基于VRRP協議VRRP協議通過為一個IP設置一個或幾個備份下一跳路由的方法來構建VIP,當某個擁有VIP節點失效后,備份節點被接管,VIP被添加,下一跳路由會替換,從而新節點可以通過VIP進行通信。使用VRRP實現的VIP每次只會在一個節點落地,這就限制了其作為LB的功能,即如果業務是跟IP綁定的,則該業務同一時刻只能在一個節點處理,無法在其他不擁有這個IP的其他節點之間進行負載均衡。但VRRP比較簡單可靠,同時實現了HA系統的節點探測,接管,遷移等事件,在HA系統要求不高的情況下,簡化了HA系統的設計。
-
基于OSPF協議基于OSPF協議的VIP需要在每個節點上預先設置好同樣的VIP,并且在每個節點上運行quagga的ospfd進程,其將鄰居關系報告給ospf三層交換機,同時可以在三層交換機上設置到這些節點ospf cost值,如果這些節點的cost值相同,則三層交換將會對所有發達這些VIP的包進行負載均衡,否則只發到cost最低的節點。ospf三層交換機通過hello包來探測與之相連的節點,如果在所設的dead時間內,沒有回應則會斷掉路由,將流量切換到另一個備用節點。這種方案的優點是如果服務是無狀態的,則做負載均衡很方便,但做HA系統的話,仍然需要各個節點自己來探測節點狀態做故障容忍,否則其他節點無法知道這個節點失效信息。還要注意的是,由于ospf的節點失效消息跟HA系統自己的故障探測可能會有時差,并且接管節點也可能不一致,這樣會導致這這種情況的發生: 1) ospf路由器已經將失效節點的流量信息切換到有效節點,但HA的故障探測并沒有將該有效節點作為takeover節點,這就會導致嚴重問題。所以必須要求ospf的takeover 節點和HA的takeover節點必須一致。 2) ospf路由器先將流量切換到了有效的takeover節點,但由于HA系統的故障探測有延遲,HA系統還沒有檢測到故障節點,這樣實際的HA系統的takeover節點還沒有準備好處理新切換過來的流量,從而導致出錯。所以為了處理這個問題,需要HA系統的takeover節點能夠容忍這個時差。
-
基于clusteripclusterip是通過iptables的模塊實現的。這個方案通過為每個節點設置同一個clusterip作為VIP,并且在每個節點上為這個VIP設置同樣的MAC地址(所有節點回包以這個MAC作為源地址),同時為每個節點設置一個節點號(node_number),發到這個VIP的包所有節點都能收到,每個節點根據算法:hash(sourceip)%node_number來判斷是否是自己的包,是就處理,否則丟棄。這個方案的優點是簡單,無需更改路由。缺點是仍然要自己維護HA節點狀態,同時由于每個包都同時發到所有節點,對系統整體性能有很大影響。
-
基于LVS這個想必阿里人都很熟,優點多多不再費口舌,我要說的是雖然其LB功能強,但其Director服務器本身就是單點故障,所以要做HA系統的話,首先要對Director進行HA改造。
DNS
DNS是另一種基于名字解析的虛接口,應用非常廣泛,幾乎所有大型網站都有基于DNS的HA實現,這里就不展開解釋了。
其他虛接口
有些服務比如中間件,會用RPC作為虛接口,客戶端不直接與后端服務打交道,而是先查詢RPC服務器來列舉后端有哪些可可供調用的服務,然后直接來調用。
虛擬網絡文件系統也是一種虛接口,通過元數據服務器來提供虛擬文件系統,文件系統空間由元數據服務器來管理,真實服務器不管理文件系統空間,客戶端通過元數據服務器來操作文件系統,而由元數據服務器來提供真正的數據服務器,數據服務器之間互相備份,單個數據服務器宕機不會導致真個文件系統崩潰。典型的例子是google 的GFS。
節點通訊
對HA節點來說,相互之間通訊是必須的,無論有無LB功能,有無狀態。這個功能可以很大也可以很小。最簡單的通訊可以通過心跳實現,兩個節點之間通過心跳協議交換狀態。復雜系統可能會針對通訊構建更復雜的子模塊。值得注意的是,通訊部分有很多故障源,就像前面提到過的一樣,這些子模塊也必須要提高故障容忍性。
對于心跳協議這里再多說幾句,心跳協議多用在雙機熱備上,即上面提到的failover模式。心跳協議主要用來在兩個節點之間相互探測對方狀態,可以通過串口線互聯,也可以通過網線互聯,值得注意的是,無論是串口線還是網線互聯,如果只是單線連接很容易會產生**腦裂問題**,所謂**腦裂問題**就是,當心跳線斷開后,雙方節點無法知曉對方狀態,都以為對方出了故障,從而出現對資源的爭搶,導致系統混亂。
腦裂問題發生的主要原因是,這個節點之間單線互聯的心跳線違背的HA三原則,存在單點故障問題,所以要解決這個問題,可以采用雙線互聯,或采用另外一條輔助心跳線。
流量調度
就像之前提到的一樣,我這里所提到的HA系統是指網絡服務HA系統,涉及到網絡服務一般都需要流量調度功能,這也基本上是標配。
這里流量調度可以簡單分為正常調度和異常調度兩類:
先說異常調度,其是指當某節點異常時,系統需要將流量調度到正常節點上繼續處理,這是故障容忍功能的一部分。不同虛接口,不同架構會有不同的實現方式。對于vrrp或ospf實現的vip接口,流量調度主要是通過改變路由器和節點的路由表來實現異常流量調度,而lvs + NAT方式則通過一個控制節點來實現異常流量調度。
對于正常調度,它主要是指Load Balance。Load Balance與HA結合是很自然的事情,一是單節點可用性比較高,如果僅用來作為備份節點實在是浪費。二則LB的很多事件跟HA相重疊,比如當進行流量調度時,需要探測節點狀態,三則HA性能的橫向擴展離不開LB。而影響LB性能指標的一個重要因素就是流量調度。具體到不同業務可以采用N多調度算法,這些算法有些也被廣泛用在操作系統中對線程的調度,簡單點的有直接對五元組hash(很多交換機甚至網卡也都支持,也有人將這種hash算法不叫LB,而叫LS(load sharing)),復雜點的有FIFO,時間片輪轉,公平隊列等,更復雜的有對QoS等進行評估,對流量進行統計等。所有這些算法都圍繞一個主題:公平。但公平這事大家都懂的,你所追求的正是你所缺少的,流量調度也難有絕對公平,所以算法無非都是在時間和空間兩個方面玩平衡。
具體有哪些算法請大家自行腦補吧,在此不一一列舉。
控制層
控制層是HA系統最重要的組件,它直接關系到HA的可用性問題。
就像Fault Tolerance節談到的一樣,控制層需要在構建和驗證兩個環節來消除/避免故障。這層可以做成Failover的簡單方式,也可做成象hadoop的zookeeper那樣的復雜系統。但無論實現簡單還是復雜都是為了解決故障處理問題,性能問題。跟上節講的一樣,現在的HA系統實現都將LB集成在一起,但邏輯上講控制層只負責故障處理,即Fault Tolarence。
控制層之所以難搞要歸結于HA系統的組成,前面提到過HA系統三原則要求之一是,節點之間需要互相獨立,獨立就是要民主嘛,而失敗的民主就是一盤散沙,更難管理了。大家都知道,對軟件問題來說,專制方式是最容易處理的,用一個皇帝節點來統管其他草民節點,簡單粗暴也很有效。但專制的問題是這個皇帝節點如果出問題了,江山就倒了。所以矛盾就產生了,牛人的解決方案就粉墨登場了,道理也很簡單,基本上是在民主方案基礎上在多搞幾個皇帝節點來個組團成一個皇帝委員會,同時委員會內皇帝節點之間也搞民主來選一個真正的領導,所有委員會內皇帝節點對外只呈現一個虛擬皇帝,所有草民節點都聽這個虛擬皇帝的話,這樣任何一個皇帝死掉,委員會內部立馬民主選一個新皇帝來頂上,而草民節點看不到這個皇宮內部爭斗大戲,仍然在聽從那個虛擬節點的領導。草民節點死掉更簡單了,皇帝節點會首先知曉,然后按實現事先設定好的規則來處理,該替換就替換,該公告就公告,如此這般江山社稷就穩固了。所以搞到最后,諸位可以看到,控制層本身就是一個HA系統了。
但無論怎么實現,一個完備控制層要處理以下幾個事情:
-
故障檢測
這是必須的,任何節點的故障需要被盡快被發現,然后被處理,不能讓單節點故障在系統中擴散,也不能讓其中斷業務。
-
節點接管
接管屬于故障處理部分,這個步驟也需要盡快完成,以避免業務中斷。
-
狀態同步
節點之間的狀態應該互為備份,當某個節點出故障時,其他節點應該有其狀態信息的拷貝。
-
狀態遷移
當接管節點準備好后,失效節點的狀態能夠順利遷移到接管節點。
-
節點集成
當新節點加入HA系統時,其他節點能夠感知其存在,并且將自身狀態信息同步到新節點。
需要指出的是,以上這些步驟雖然屬于控制層,但有時業務層也需要感知,比如業務是數據庫,當節點失效時,數據庫數據有可能出現不一致情況,此時控制層要將以上這些事件傳遞給數據庫系統,數據庫系統然后可以根據故障信息將數據恢復到以前的checkpoint.
業務層
業務層的任務是運行具體的服務,有兩種形式的服務,一種是帶狀態的,另一種是不帶狀態的。所謂狀態是指服務運行過程中產生的能夠影響服務運行的一些數據。比如tcp會話中的各種會話狀態,數據庫的session等等。由于這些數據是由業務來定義,所以需要業務層來處理。對不帶狀態的業務來說,處理起來就容易多了,這種情況下,無需狀態同步,錯誤處理,節點集成,接管都很容易,每個節點都變成來料加工工廠,招之即來,揮之即去。一些AS/AA結構交換機正是通過這樣的failover形式構造HA系統。
對帶狀態的業務,業務層除了關注自身業務外,還需要關注狀態同步,狀態數據的一致性問題。有些復雜系統還會有作業調度系統,這個不是普通的LB,而是包括計算和數據在內的綜合調度,比LB更優化了。
依賴具體的業務不同,狀態同步有時會變得很麻煩,甚至難以處理,比如ipsec HA中的包序號同步問題,這個序號是ipsec協議用來抗重放攻擊的,每發送一個加密包這個序號會加1,這個序號就是一個狀態數據,必須要同步到其他節點,以防這個節點失效后,其他節點能夠從這個序號開始繼續發送加密包,否則對端ipsec V*N服務器可能會將收到的包丟棄。現在的問題是,如果每次序號變化都同步到其他節點,隧道多的話,這會導致狀態同步代價太高,性能大打折扣。不過幸好ipsec rfc提供了一個補救措施,即ipsec抗重放窗口可以接收比窗口右邊沿大的序號,這樣就可以不用連續同步序號,而是以一個步長的方式來同步了。但即使是這樣,ipsec的ike協商階段狀態仍然沒有被同步,因為這個階段狀態太多,變化太迅速,而且涉及內部太多數據結構,目前的方案是,由于這些狀態只發生在一個獨立節點上,如果該節點失效,其他節點接管時重新初始化這些連接即可。這里只給出ipsec HA作為例子說明狀態同步問題,其他業務在實施HA之前必須要考慮到狀態同步問題,可以采用的方案也比較多,像checkpoint,重新初始化等都可以。
狀態同步的另一個要考慮的問題是數據一致性問題。雖然可信賴計算沒有將數據一致性納入其中,但在實施HA時必須加以考慮。著名的CAP理論已經揭示了當數據被分割后,你就只能在數據的可用性和一致性二者中選其一了,而不能二者兼得。當然這也依賴HA的實施架構,如果采用sharing-disk方式,數據一致性就不會有大問題了。否則就要像各種分布式cluster方式一樣要考慮當數據被分區后,怎樣在數據一致性和可用性之前平衡了。這里不展開了,有興趣再去互聯網垃圾場翻幾遍,肯定能挖到寶。
HA系統模式
前面提到現在的HA系統一般都結合了LB,HA系統主要解決單點故障問題,LB主要解決熱節點問題,這兩方面問題有很多共性,節點過熱的話會導致過載最終可能造成節點失效,而節點失效后又可能會導致其他節點更熱,從而形成雪崩效應,最終導致整個系統崩潰。如果把熱節點看成一個缺陷的話,必須在構造階段想辦法避免,而這就是Fault Tolerance范疇了。LB是解決熱節點的有效方法,所以從這點可以看出,LB也是一個有效的Fault Tolerance方法。而同時HA用來做Fault Tolerance的一些事件也可以被用來處理LB,所以可以看出它們是一對好基友。
從HA系統實施架構來看,各個分層不一定象上面那么清晰,而是根據具體業務需求來做最優調整,下面羅列了一些常見的HA系統架構:
Failover架構
Failover架構是一種簡單架構,前面也提到過,是一種雙機熱備,只有兩個節點,一主一備。以前也有冷備,但可以想象,冷備極大的降低了可用性,一些硬件HA系統可能還有使用,但在網絡服務方面沒人使用。對熱備來說也有共享存儲和不共享存儲兩種:不共享存儲的failover架構如下圖所示:
這種結構一般用在無節點狀態的系統中,比如交換機,也有通過VRRP之類協議來同步路由的AA/AS failover路由器采用這種架構。
共享外置存儲的failover架構如下圖所示:
很多數據failover系統采用這種共享外置存儲的架構,主要是數據庫系統有很多狀態,這種架構將狀態保存到共享的外置存儲后,主節點本身狀態就無需同步到備用節點,簡化了故障容忍性設計。
平等節點架構
平等節點架構中所有節點地位都是平等的,也就是所謂的sharing-nothing結構。就象前面闡述的一樣,平等意味著民主,民主意味著權利下放,而權利也同時意味著責任,這也就說單個節點需要承擔更多責任,這些責任便是如何來共同維護HA系統的可用性。有一些成熟的協議已經在HA系統的控制層面幫我們做了這些事情,比如VRRP協議。但業務狀態同步問題還是需要業務服務自己來解決。我們的ipsec V*N網關便是采用這種架構。平等節點架構如下圖所示:
共享存儲架構
也就是sharing-disk結構。共享外存架構的有點前面也提到過了,就是節點的業務狀態同步可以大幅簡化了,頂多是在節點失效或集成時進行狀態回滾。這種架構一般要依賴一個具有高可用性的外置存儲網絡,比如SAN,FB,這些外置存儲I/O的速度可以跟DAS設備(即本機磁盤)比擬。這樣一來數據一致性問題變得不那么關鍵了,但I/O卻成了系統的熱點。架構如下圖所示:
多HA系統結構
這樣的HA系統里可能存在多個子HA系統,前面提到的hadoop zookeeper便是一個例子。這種系統的優點是,針對具體問題各個擊破,誰熱就給其降溫(LB),誰危險就對其做HA。架構如下圖所示:
可以看出,圖中由多zookeeper server組成一個HA子系統為所有client節點服務,整個系統又是一個大的HA系統。
HA系統指標
對于HA系統來說,可用性是其最重要的一項指標,雖然可信賴計算組列出了六大屬性,但我覺得從實用角度來說,可維護性,數據一致性,性能指標應該要重點關注。
其中可維護性又可以分為如下幾個指標:
-
故障恢復時間
-
故障隔離能力
-
升級能力
性能指標又可分為如下兩點:
-
負載均衡能力
-
橫向擴充能力
我不打算列一大堆公式來分析這些指標,因為每一種都有人做了詳盡的研究,如果有人想分析,網上很容易找到相關資料,我這里只列出我們需要的關注點。
后記
絮絮叨叨說了那么多,好像也沒新東西啊,現實就是這樣,很多道理就像白開水,大家都懂,如果直接在課堂上喂你,你估計不喝,但如果調和一下,加點料,做成心靈雞湯,你就覺得還蠻有滋味的,然后喝得很開心。所以我這篇文章也希望能將這些已有的東西整理加工一下,同時加了一些自己的料,做成料理,如果口味不好的話,還望看官見諒啊。
copy這詞已經被重新發明了很多版本,不同人有不同叫法,律師叫剽竊,普通人叫模仿,打工皇帝叫復制,深圳華強北叫山寨,文人叫拾人牙慧,教授叫研究,學渣叫抄襲,發明家叫借鑒,牛頓叫站在巨人肩膀上,導演叫向xx致敬。如果說我這篇文章有些價值,那是因為站在了牛人的肩膀上,研究了很有價值的文章,比如wiki, lvs,vrrp, ibm等, 在此一并向他們致敬。
說了這里,各位看官可能會問,你標題是HA啟示錄,那你的啟示呢?放心,我不是標題黨,還記得HA系統的三原則么?第一條是不能有單點故障,我們每個人作為獨立的節點,無論在項目中,還是在公司里也不能出現單點故障問題,就是說,不要因為你的問題導致公司或項目玩不轉,這個時侯就是你被替換,備份節點上線的時候了。第二條是可靠互聯,我們自己要與上下游節點之間形成互聯互通的可靠通信,否則封閉的節點無法組成完整的系統。第三條是故障檢測機制,就是說我們要及時更新自己的狀態,早請示晚匯報,要讓自己問題被各節點及時知曉,不要積累問題,和擴散問題,導致系統架構的不可靠,因為前面說過了,單個節點本不可靠,出問題是正常的,但如果不檢測和報告自己的問題,就是你自己的問題了,也就是你這個節點該修理的時候了。
參考文獻
-
Sam Siewert (Sam.Siewert@Colorado.edu), Adjunct Professor, University of Colorado: Big iron lessons, Part 2: Reliability and availability: What's the difference?
-
Jean-Claude Laprie: Dependable Computing: Concepts, Limits, Challenges
-
Sangeetha Seshadri, Ling Liu, Brian F. Cooper ({sangeeta,lingliu,cooperb}@cc.gatech.edu), Lawrence Chiu, Karan Gupta, Paul Muench({lchiu,guptaka,pmuench}@us.ibm.com): A Fault-Tolerant Middleware Architecture for High-Availability Storage Services
-
Magnus Gammelg?rd, Mathias Ekstedt, Per N?rman : Architecture Scenario Analysis – Estimating the Credibility of the Results
-
Paulo Vera-Ssimo,Luís Rodrigues: Distributed Systems for System Architects
-
http://cailin.iteye.com/blog/2014486: zookeeper原理
-
wikipedia 掃碼關注阿里技術保障公眾號,有更多技術干貨分享,更有機會贏取精美禮品。
-
</ol> </div>