官术网_书友最值得收藏!

1.2 高并發系統的設計難點

在Web 2.0時代,涌現出了許多擁有海量用戶的應用,它們所承受的并發流量是Web 1.0時代的網站無法想象的。如此大的并發流量,給系統帶來的技術挑戰是前所未有的。對承受如此大并發流量的高并發系統來說,系統設計的難點主要有兩個:系統的高可用和訪問的高性能。

1.2.1 系統的高可用

在維基百科中,高可用(high availability,HA)的定義是系統無中斷地執行其功能的能力,代表系統的可用性程度,是進行系統設計時的準則之一。系統無中斷地運行其功能的時間越長,代表系統的高可用越好。在很多開源組件中,都有保證高可用的方案。

例如,Redis的官方文檔中專門有一部分用來介紹Redis的高可用方案——哨兵(sentinel),該方案的示意如圖1-1所示。哨兵節點是一組獨立部署的進程,每個進程會定期向Redis主節點和從節點發送命令,探測它們是否存活。如果主節點沒有正確地響應命令,那么哨兵節點就會觸發Redis集群的主從切換,重新為Redis集群指定一個能夠正常運行的從節點作為主節點。

圖1-1 哨兵高可用方案的示意

再如,在Hadoop 1.0中,用來存儲集群元信息的NameNode只有一個,沒有提供高可用方案。NameNode相當于整個Hadoop集群的心臟,一旦發生故障對整體系統的影響非常大,因此Hadoop 2.0提供了NameNode的高可用方案,即系統中除了存在一個正常運行的NameNode(active NameNode),還存在一個備用NameNode(standby NameNode)。正常運行的NameNode和備用NameNode之間可以通過共享存儲文件來共享數據。當正常運行的NameNode發生故障時,備用NameNode會自動代替故障的NameNode,成為新的正常運行的NameNode提供給集群使用。

對于任何系統來說,保證系統的高可用是一名開發人員的首要任務,而在現實的系統運維過程中,影響系統可用性的原因有很多。下面就介紹幾個重要的原因。

影響系統可用性的一個原因是系統可能隨時發生災難性的“黑天鵝”事件,這對整體系統可用性的影響是巨大的。龐大的系統中存在海量的服務和資源,這些服務和資源之間的關系錯綜復雜。即使開發和運維人員在保障系統高可用方面采取了多種措施,也很難做到盡善盡美。一個小的疏漏可能就會導致系統的全盤崩潰。

例如,2022年12月18日,阿里云香港Region的可用區C出現了一次近14個小時的故障[],故障的原因簡單來說就是機房里的制冷系統出現了問題,機房里4套主備制冷系統共用了一套水路循環系統,導致制冷系統無法做到主備切換,必須花3個多小時等待制冷設備供應商來現場處理;供應商來了之后,又花了2個多小時對制冷系統進行了補水排氣,結果在嘗試重啟制冷設備的時候,發現制冷系統存在一個群控的邏輯,導致無法重啟單臺制冷設備。于是,供應商又花了3個多小時來解除這個群控邏輯,并且對全部4臺制冷設備進行了重啟。在故障發生了近11個小時之后,機房的溫度終于趨于穩定了。


[1] 此案例于2024年9月20日引自阿里云發布的“關于阿里云香港Region可用區C服務中斷事件的說明”。

在整個處理過程中還發生了一個插曲,就是在整體機房溫度沒有恢復正常的時候,機房的一個包間竟然觸發了強制消防噴淋,所以在機房溫度恢復正常之后,阿里云沒有對這個包間的服務器直接上電,擔心服務器進水導致數據丟失,因此阿里云又不得不對觸發強制消防噴淋的包間內的服務器做了數據完整性校驗,這個過程又延續了3個多小時。

總結這個案例可以得出,無論是設計系統還是設計系統故障時的應急響應都需要注意以下3個關鍵點。

不能忽視系統中的單點問題。例如,制冷系統存在單點問題,雖然有主備制冷系統,但是它們共用一套水路循環系統,一旦水路循環系統發生故障,主備制冷系統都不能正常工作。

做好預案,且要經過完善的故障演練。預案不足或預案沒有經過完善的故障演練,可能導致切換備用制冷系統不成功;又因存在群控邏輯而無法重啟單臺制冷設備,需要由供應商現場修改配置來解除群控邏輯,導致故障的解決時間延長了幾個小時。對于一些互聯網系統,尤其是“頭部”互聯網公司的核心系統,系統的高可用至關重要,即使出現一個小時的故障都可能帶來不可估量的損失。

高可用策略不能只是理論上的高可用,需要能在實踐中真正發揮作用。2021年,我維護的一個系統就出現了“只是理論上的高可用”的問題。當時,我維護的系統已經在云上做了多可用區部署,保證發生故障時可以把系統流量從一個可用區切換到另一個可用區,但是因為部署流量切換系統、監控系統、報警系統等多個運維系統的可用區恰好發生了故障,導致高可用策略失效。

當然,“黑天鵝”事件發生的概率非常小,可一旦發生,對于系統來說就是致命的災難。然而無獨有偶,在2023年,國內因為機房制冷系統故障導致的系統長時間故障又接連發生了2起。此類故障不僅會給公司帶來巨大的經濟損失,還會嚴重影響用戶體驗和傷害公司信譽等。因此,排除故障隱患、演練故障預案,是降低“黑天鵝”事件影響的必做之事。

影響系統可用性的另一個原因是突發流量。突發流量的典型載體是以微博為代表的社交媒體,它們經常會因突發流量而出現不可用的問題。大型的社交媒體往往擁有海量的用戶,極大地加快了信息流動的速度。用戶可以非常便捷地在社交媒體上獲取信息,一些熱點事件也更容易在社交媒體上發酵,短時間內帶來大量的用戶訪問請求,給系統帶來極大的沖擊,影響系統的可用性。

影響系統可用性的更重要原因是系統變更。《SRE:Google運維解密》一書中提到:SRE的經驗告訴我們,大概70%的生產事故由某種部署的變更而觸發。這里提到的變更不僅僅是代碼的變更,也包括數據的變更和配置的變更等。因此,開發團隊需要關注變更的流程,如規定合適的變更時間、變更前準備必要的檢查清單等,這部分內容將在6.5.1節詳細介紹。

1.2.2 訪問的高性能

系統性能是影響用戶體驗的直接因素,谷歌針對網頁的用戶體驗提出了一個指標——與下一次繪制的交互(interaction to next paint,INP),它會在網頁的生命周期中記錄用戶與網頁所有交互的延遲時間(包含輸入延遲、處理延遲和展示延遲),以度量網頁對用戶交互的總體響應速度。低INP意味著網頁能夠可靠地響應用戶交互。INP分為以下3個等級。

INP小于等于200 ms:表明網頁的響應速度良好,用戶基本感知不到網頁的刷新和渲染。

INP大于200 ms但是小于等于500 ms:表明網頁響應速度有一定的優化空間。

INP大于500 ms:表明網頁響應性差,用戶體驗也比較差,需要進行網頁加載優化。

優化INP的方式是多種多樣的,如減少請求服務端次數、優化接口響應時間、延遲加載、使用頁面緩存等。在服務端優化INP是非常直接的方式之一,而優化接口響應時間一般有以下兩個思路:

提高系統的并行能力,讓系統在單位時間內能夠處理更多請求;

縮短單次請求的響應時間。

下面分別介紹這兩個思路。

1.提高系統的并行能力

阿姆達爾定律(Amdahl’s law)由吉恩·阿姆達爾(Gene Amdahl)在1967年提出,是描述計算機系統設計的重要定量原理之一。在高并發系統設計中,阿姆達爾定律描述的是在固定負載下,并發進程數與響應時間之間的關系。

在固定負載下,并行計算加速比(即進行并行化處理后,系統處理任務的效率提升情況)可以定義為RR越大表示并行化處理后效率提升越明顯,即系統響應時間越短;R越小表示并行化處理后效率提升越不明顯,即系統響應時間越長。R可以用式(1.1)表示:

(1.1)

其中,表示任務中串行進程的計算量,表示任務中并行進程的計算量,n表示并行化處理的節點個數。從式(1.1)可以推導出式(1.2):

(1.2)

其中,n表示并行化處理的節點個數,p表示并行任務數占總體任務數的比例。

p=1時,即任務全部是并行任務時,R=n;當p=0時,即任務全部是串行任務時,R=1,也就是完全無加速;當n趨近于無窮大時,也就是擁有無限個并行化處理節點時,R=1/(1?p),此時Rp正相關,即并行任務數占總體任務數的比例越高,R越大。

2.縮短單次請求的響應時間

想要縮短單次請求的響應時間,首先要判斷系統是CPU密集型還是I/O密集型的,因為優化不同類型的系統性能的方式不盡相同。

CPU密集型系統需要處理大量的CPU運算,因此選用更高效的算法或者減少CPU運算次數就是這類系統性能的優化方式。例如,如果系統的主要任務是計算哈希值,那么這時選用更高效的哈希算法就可以大大提升系統的性能。發現CPU過載問題的主要方式,是通過一些CPU剖析工具(如針對Linux系統的perf、eBPF、gperftools等)來找到消耗CPU時間最多的方法或者模塊。

I/O密集型系統的主要特點是系統中請求的大部分時間都用在等待I/O讀寫操作完成。當前大多數互聯網系統都屬于I/O密集型系統。如果觀察這類系統的運行指標,就會發現系統中計算資源的CPU使用率的峰值基本上在40%~50%,這就是因為系統中請求的大部分時間都用在等待I/O讀寫操作完成了,如等待數據庫、緩存中的數據返回,或者等待依賴的其他服務的請求返回,CPU反倒處于相對空閑的狀態。這類系統的優化方式多是減少I/O讀寫操作的次數和耗時,如優化數據庫的慢查詢,使用速度更快、性能更好的緩存來減少對數據庫的請求,使用連接池來減少連接的頻繁創建,等等。

主站蜘蛛池模板: 肇东市| 和政县| 巴中市| 凤庆县| 司法| 西藏| 伊宁市| 武功县| 贵阳市| 贵阳市| 祁东县| 东至县| 准格尔旗| 乌兰察布市| 木兰县| 遵化市| 门源| 长垣县| 灵丘县| 华亭县| 淮南市| 永川市| 如皋市| 奇台县| 颍上县| 临夏县| 宁化县| 板桥市| 嘉鱼县| 阜南县| 凯里市| 盐城市| 岳阳县| 屏山县| 连南| 文水县| 蒙山县| 大化| 稷山县| 永新县| 阳东县|