除了避免單點外,降低耦合也是設計高可用性系統時應考慮的重點,通??梢圆扇‘惒交瘉斫档婉詈?,將非關鍵邏輯和關鍵邏輯隔離開,例如在淘寶上買一件商品,確認購買了后,需要旺旺通知賣家,如果旺旺通知賣家這個過程是同步通知的話,對于系統來說無疑增加了一個風險點,因此可以將旺旺通知賣家的步驟變為異步的方式來做,這種場景的異步通常又采用消息中間件來實現;還有另外一種場景也經常采用異步化的方式來降低耦合,例如打開天貓的商品詳情時,都會有相關商品的推薦,如果這個推薦系統出問題的話,就會導致商品詳情也看不到了,因此這里也可以采用異步化來加載推薦系統,在這種場景中通常采用Ajax帶超時的方式來實現。
各網站在總結多年的可用性系統設計的經驗時,有一個設計原則被所有網站列入:保持簡單,簡單的方案意味著容易掌控,而復雜的方案一方面意味著實現難度大,另一方面意味著出現問題時很難排查。
可控性也是各網站強調的重點,可控性就意味著一切的代碼都在掌握下,并且最好是每個使用到的部分都有專業的人士(對可用性要求越高,在這點上要求也就越高),這樣才能清楚在出現問題的時候是哪個地方造成的,并且可以自行排查和解決,如不可控,則意味著一旦出現問題,就得依賴第三方來排查,那這個時間就非常不可控了,這也是網站不采用商用軟件的重要原因。
編寫高質量軟件是保障系統高可用性的重要一環(可控性也是編寫高質量軟件的基礎),但軟件幾乎不可能做到0 bug,各網站在總結自己保障高可用的經驗中提到了一些策略用于保障系統的高可用,這些策略主要包括:監控/報警、容錯、自我保護、隔離、和降級,需要做到高可用的軟件在交付時都應具備這些特性。
監控/報警是軟件自身能夠保障高可用的重要策略,就像是汽車的儀表盤一樣,可以告訴你油還剩多少,速度是多少,胎壓是否正常等重要信息,對于軟件而言,同樣需要讓外部可以獲取到其運行的狀況,例如Google的軟件都會提供一個html的頁面供使用者或開發人員訪問(用過Hadoop的人也會發現這個特征),在這個頁面上可通過key/value的方式來獲取系統的一些運行指標,對外RPC的系統Google會采集所有的正常請求、錯誤請求以及其消耗時間的分布狀況(>0.05s的,>0.1s等),除了監控系統的運行狀況外,也需要提供一些方式以便外部能簡單判斷系統運行是否正常,例如curl某頁面等,對于不正常的現象要進行即時的報警,以盡可能做到在故障尚未影響到用戶時進行解決。
軟件會依賴很多外部的因素,例如機房、硬件、數據庫、服務等,而所有依賴的部分都是有可能出現故障的(要堅信這點,互聯網的特色是所有小概率事件都會發生),在設計軟件時需要考慮當依賴方出問題時,如何能保障軟件本身的可用性,因此一定要做一些容錯的處理,例如對于機房故障,各網站通常都會租用或建設多機房來避免;又例如Google采用IDE硬盤來存儲文件,不做Raid,于是采用了復制三份的策略來避免硬盤故障導致數據丟失。
軟件通常會接受外部的輸入,而有些時候輸入條件的不符合預期可能會導致軟件的故障,在我們的系統中曾經出現的一個故障案例:某系統對外提供了批量查詢的功能,結果有一次客戶端提交了一個查找10000個用戶的批量查詢,導致系統由于內存不夠出現了故障,因此在設計軟件時需要保障處理自己能力范圍的請求,對于超出能力的請求可以考慮直接拋錯,還有一種常見的是后端處理變慢導致雪崩效應的故障,這種在軟件上通常會采用超時、限流等方式來避免,對于這些可能出現的故障在設計軟件時都應考慮采取一些保護的措施來保護自身的可用性。
軟件通常提供了多種功能,這些功能會有重要的和不重要的,如果由于不重要的功能異常導致重要的功能出現問題,顯然是不合算的,因此在設計軟件時需要充分的考慮異常的隔離,不互相影響,例如在Google的系統設計中會采用Prioritized Request等策略。
降級即為James Hamilton的那篇著名的《On Designing and Deploying Internet-Scale Services》論文中提到的Graceful Degradation,降級通常采用的方法是在故障將要出現或出現后,通過關閉系統的一些功能來降低故障產生的影響,例如網站上有些操作可能是特別耗資源的,而這些資源的消耗又可能會導致影響到核心功能,一旦出現影響時,就可以通過關閉這些功能保障核心功能的可用,降級通常用于臨時的繞開故障,故障的原因則事后排查。
交付具備高可用特征的軟件是開發人員的重要職責,而對于一個網站而言,軟件不是一次性交付的,也不是好幾年才升級一次的,而是頻繁交付的,因此對軟件本身的維護也是保障高可用的重要環節。
通常,系統的不可用是變更造成的,如何降低變更對系統可用性造成的影響,是各網站都關注的重點,Google在發布時通常采取“滾木移石”的方法、Facebook則通常采用Dark launch的方法,以降低變更帶來的影響。
人工來操作系統的變更是故障產生的隱患,因此各網站基本都會推薦多種工具來實現系統變更的自動化,例如采用puppet來實現自動化的部署。
除了發布這個重要環節外,處理故障也是維護的重要工作,系統總是會有出現故障的時候的,出現故障時如何快速的處理來降低對可用性的影響也成為了網站一直關注的重點,前文已經說到可控性對解決故障的幫助,除了可控外,各網站也會研究一些其他的方法,Facebook就采用了FBAR來自動處理部分故障,這顯然可以一定程度降低故障產生的影響。
性能
在前文中提到的可控性同樣也是保證性能的重點,只有明確的知道調用的每個API,依賴的環境(包括軟硬件)的細節原理,才能編寫出高性能的軟件。
從系統結構上來看,我們可以看到各大網站在發展到今天的時候,為了保障高性能都采用了類似的方法,首先是前端Web系統這塊,都采用了可編譯為機器碼的方式,例如即使是Facebook采用php,其仍然研發了一個可自動轉化為C++代碼的產品來提升運行效率。
設計系統時應考慮將沒有前后依賴的邏輯并行化處理,,或者將大的請求進行拆分,例如在Google上進行搜索,Google會進行分詞,然后并行的進行索引的查詢,從而提高響應速度。
基本上各大網站都極度依賴Cache,這原因很明顯,內存的訪問速度遠快于磁盤,依賴Cache的場景中最需要做到的是數據一致性的合理保障,一個典型的場景是數據更新時保障Cache一致性的策略,Cache的更新和數據的更新如果要做成一個事務顯然有不小的難度,此時網站常采用一個簡單策略來保障,就是先失效Cache,再更新數據,等到下次系統去訪問此數據時,才更新到內存。
原文轉自:http://bluedavy.me/?p=396