B 站崩了,總結下「高可用」和「異地多活」

你好,我是悟空。

一、背景

不用想象一種異常場景了,這就真實發生了:B 站晚上 11 點突然掛了,網站主頁直接報 404。

手機 APP 端數據加載不出來。

23:30 分,B 站做了降級頁面,將 404 頁面跳轉到了比較友好的異常頁面。

但是刷新下頁面,又會跳轉到 404 頁面。

22:35 主頁可以加載出數據了,但是點擊動態還是會報 502

點擊某個視頻,直接報 404。

2021-07-14 02:00 之後 B 站開始逐漸恢復。

二、什麼原因

今日凌晨 2 點,B 站發佈公告稱,昨晚,B 站的部分服務器機房發生故障,造成無法訪問。技術團隊隨即進行了問題排查和修復,現在服務已經陸續恢復正常。而針對網友傳言的 B 站大樓失火一事,上海消防官博進行了闢謠,B 站大樓並未出現火情。

圖片

看來 B 站的高可用並不令我們滿意。接下來我們來探討下什麼是高可用以及跨機房部署的思路。本篇正文內容如下:

三、到底什麼是高可用

經過了 2 個小時,B 站纔開始逐漸恢復,那 B 站系統到底算不算高可用呢?

首先高可用是個相對的形容詞。那什麼是高可用呢?

3.1 高可用

高可用性(High Availability,HA)我們已經耳熟能詳,指的時系統具備較高的無故障運行的能力。

B 站針對高可用架構還做過一篇分享:

https://cloud.tencent.com/developer/article/1618923

重點:以後 B 站面試這類題不考,望周知。

常見的高可用的方案就是一主多從,主節點掛了,可以快速切換到從節點,從節點充當主節點,繼續提供服務。比如 SQL Server 的主從架構,Redis 的主從架構,它們都是爲了達到高可用性,即使某臺服務器宕機了,也能繼續提供服務。

剛剛提到了快速,這是一個定性詞語,那定量的高可用是怎麼樣的?

3.2 定量分析高可用

有兩個相關的概念需要提及:MTBF 和 MTTR。

MTBF:故障間隔時間,可以理解爲從上次故障到這次故障,間隔多久,間隔的越長,系統穩定性越高。

MTTR:故障平均恢復時間,可以理解爲突然發生故障了,到系統恢復正常,經歷了多長時間,這個時間越短越好,不然用戶等着急了,會收到很多投訴。

可用性計算公式:MTBF/(MTBF+MTTR)* 100%,就是用故障的間隔時間除以故障間隔時間+故障平均恢復時間的總和。

通常情況下,我們使用幾個九來表示系統的可用性,之前我們項目組的系統要求達到年故障時間不超過 5 分鐘,也就是五個九的標準。

3.3 定量分析 B 站

來反觀下 B 站故障了多久,2021-07-13 23:00 到 2021-07-14 02:00,系統逐漸恢復,如果按照年故障總時間來算的話:B 站故障超過 1 個小時了,只能算達到了三個九的標準。如果按照日故障時間來算,只能達到兩個九的標準,也就是 99% 的高可用性,有點慘...

3.4 一個九和兩個九

非常容易達到,一個正常的線上系統不會每天宕機 15 分鐘吧,不然真用不下去了。

3.5 三個就和四個九

允許故障的時間很短,年故障時間是 1 小時到 8 小時,需要從架構設計、代碼質量、運維體系、故障處理手冊等入手,其中非常關鍵的一環是運維體系,如果線上出了問題,第一波收到異常通知的肯定是運維團隊,根據問題的嚴重程度,會有不同的運維人員來處理,像 B 站這種大事故,就得運維負責人親自上陣了。

另外在緊急故障發生時,是否可以人工手段降級或者加開關,限制部分功能,也是需要考慮的。之前我遇到過一個問題,二維碼刷卡功能出現故障,辛虧之前做了一個開關,可以將二維碼功能隱藏,如果用戶要使用二維碼刷卡功能,統一引導用戶走線下刷卡功能。

3.6 五個九

年故障時間 5 分鐘以內,這個相當短,即使有強大的運維團隊每天值班也很難在收到異常報警後,5 分鐘內快速恢復,所以只能用自動化運維來解決。也就是服務器自己來保證系統的容災和自動恢復的能力。

3.7 六個九

這個標準相當苛刻了,年故障時間 32 秒。

針對不同的系統,其實對幾個九也不相同。比如公司內部的員工系統,要求四個九組以,如果是給全國用戶使用,且使用人數很多,比如某寶、某餓,那麼就要求五個九以上了,但是即使是數一數二的電商系統,它裏面也有非核心的業務,其實也可以放寬限制,四個九足以,這個就看各家系統的要求,都是成本、人力、重要程度的權衡考慮。

四、如何做到高可用

高可用的方案也是很常見,故障轉移、超時控制、限流、隔離、熔斷、降級,這裏也做個總結。

也可以看這篇:雙 11 的狂歡,乾了這碗「流量防控」湯

4.1 限流

對請求的流量進行控制, 只放行部分請求,使服務能夠承擔不超過自己能力的流量壓力。

常見限流算法有三種:時間窗口、漏桶算法、令牌桶算法

4.1.1 時間窗口

時間窗口又分爲固定窗口和滑動窗口。具體原理可以看這篇:東漢末年,他們把「服務雪崩」玩到了極致(乾貨)

固定時間窗口

原理:固定時間內統計流量總量,超過閥值則限制流量。

缺陷:無法限制短時間之內的集中流量。

滑動窗口原理

原理:統計的總時間固定,但時間段是滑動的。

缺陷:無法控制流量讓它們更加平滑

時間窗口的原理圖在這裏:

4.1.2 漏桶算法。

原理:按照一個固定的速率將流量露出到接收端。

缺陷:面對突發流量的時候,採用的解決方式是緩存在漏桶中,這樣流量的響應時間就會增長,這就與互聯網業務低延遲的要求不符。

4.1.3 令牌桶算法

原理:一秒內限制訪問次數爲 N 次。每隔 1/N 的時間,往桶內放入一個令牌。分佈式環境下,用 Redis 作爲令牌桶。原理圖如下:

總結的思維導圖在這裏:

4.2 隔離

  • 每個服務看作一個獨立運行的系統,即使某一個系統有問題,也不會影響其他服務。

而常規的方案是使用兩款組件:Sentinel 和 Hystrix。

4.3 故障轉移

故障轉移分爲兩種:

  • 完全對等節點的故障轉移。節點都是同等性質的。
  • 不對等節點的故障轉移。不對等就是主備節點都存在。

對等節點的系統中,所有節點都承擔讀寫流量,並且節點不保存狀態,每個節點就是另外一個的鏡像。如果某個節點宕機了,按照負載均衡的權重配置訪問其他節點就可以了。

不對等的系統中,有一個主節點,多個備用節點,可以是熱備(備用節點也在提供在線服務),也可以是冷備(只是備份作用)。如果主節點宕機了,可以被系統檢測到,立即進行主備切換。

而如何檢測主節點宕機,就需要用到分佈式 Leader 選舉的算法,常見的就有 Paxos 和 Raft 算法,詳細的選舉算法可以看這兩篇:

4.4 超時控制

超時控制就是模塊與模塊之間的調用需要限制請求的時間,如果請求超時的設置得較長,比如 30 s,那麼當遇到大量請求超時的時候,由於請求線程都阻塞在慢請求上,導致很多請求都沒來得及處理,如果持續時間足夠長,就會產生級聯反應,形成雪崩

還是以我們最熟悉的下單場景爲例:用戶下單了一個商品,客戶端調用訂單服務來生成預付款訂單,訂單服務調用商品服務查看下單的哪款商品,商品服務調用庫存服務判斷這款商品是否有庫存,如有庫存,則可以生成預付款訂單。

雪崩如何造成的?

  • 第一次滾雪球:庫存服務不可用(如響應超時等),庫存服務收到的很多請求都未處理完,庫存服務將無法處理更多請求。
  • 第二次滾雪球:因商品服務的請求都在等庫存服務返回結果,導致商品服務調用庫存服務的很多請求未處理完,商品服務將無法處理其他請求,導致商品服務不可用
  • 第三次滾雪球:因商品服務不可用,訂單服務調用商品服務的的其他請求無法處理,導致訂單服務不可用。
  • 第四次滾雪球:因訂單服務不可用,客戶端將不能下單,更多客戶將重試下單,將導致更多下單請求不可用。

所以設置合理的超時時間非常重要。具體設置的地方:模塊與模塊之間、請求數據庫、緩存處理、調用第三方服務。

4.5 熔斷

關鍵字:斷路保護。比如 A 服務調用 B 服務,由於網絡問題或 B 服務宕機了或 B 服務的處理時間長,導致請求的時間超長,如果在一定時間內多次出現這種情況,就可以直接將 B 斷路了(A 不再請求B)。而調用 B 服務的請求直接返回降級數據,不必等待 B 服務的執行。因此 B 服務的問題,不會級聯影響到 A 服務。

熔斷的詳細原理可以看這篇:東漢末年,他們把「服務雪崩」玩到了極致(乾貨)

4.6 降級

關鍵字:返回降級數據。網站處於流量高峯期,服務器壓力劇增,根據當前業務情況及流量,對一些服務和頁面進行有策略的降級(停止服務,所有的調用直接返回降級數據)。以此緩解服務器資源的壓力,保證核心業務的正常運行,保持了客戶和大部分客戶得到正確的響應。降級數據可以簡單理解爲快速返回了一個 false,前端頁面告訴用戶“服務器當前正忙,請稍後再試。”

  • 熔斷和降級的相同點?
    • 熔斷和限流都是爲了保證集羣大部分服務的可用性和可靠性。防止核心服務崩潰。
    • 給終端用戶的感受就是某個功能不可用。
  • 熔斷和降級的不同點?
    • 熔斷是被調用放出現了故障,主動觸發的操作。
    • 降級是基於全局考慮,停止某些正常服務,釋放資源。

五、異地多活

5.1 多機房部署

含義:在不同地域的數據中心(IDC)部署了多套服務,而這些服務又是共享同一份業務數據的,而且他們都可以處理用戶的流量。

某個服務掛了,其他服務隨時切換到其他地域的機房中。

現在服務是多套的,那數據庫是不是也要多套,無非就兩種方案:共用數據庫或不共用。

  • 共用一套機房的數據庫。

  • 不共用數據庫。每個機房都有自己的數據庫,數據庫之間做同步。實現起來這個方案更復雜。

不論使用哪種方式,都涉及到跨機房數據傳輸延遲的問題。

  • 同地多機房專線,延遲 1ms~3 ms。
  • 異地多機房專線,延遲 50 ms 左右。
  • 跨國多機房,延遲 200 ms 左右。

5.2 同城雙活

高性能的同城雙活,核心思想就是避免跨機房調用:

保證同機房服務調用:不同的 PRC(遠程調用) 服務,向註冊中心註冊不同的服務組,而 RPC 服務只訂閱同機房的 RPC 服務組,RPC 調用只存在於本機房。

保證同機房緩存調用:查詢緩存發生在本機房,如果沒有,則從數據庫加載。緩存也是採用主備的方式,數據更新採用多機房更新的方式。

保證同機房數據庫查詢:和緩存一樣,讀取本機房的數據庫,同樣採用主備方式。

5.3 異地多活

同城雙活無法做到城市級別的容災。所以需要考慮異地多活。

比如上海的服務器宕機了,還有重慶的服務器可以頂上來。但兩地距離不要太近,因爲發生自燃災害時有可能會被另外一地波及到。

和同城雙活的核心思想一樣,避免跨機房調用。但是因爲異地方案中的調用延遲遠大於同機房的方案,所以數據同步是一個非常值得探討的點。提供兩種方案:

  • 基於存儲系統的主從複製,MySQL 和 Redis 天生就具備。但是數據量很大的情況下,性能是較差的。
  • 異步複製的方式。基於消息隊列,將數據操作作爲一個消息放到消息隊列,另外的機房消費這條消息,操作存儲組件。

5.4 兩地三中心

這個概念也被業界提到過很多次。

兩地:本地和異地。

三中心:本地數據中心、同城數據中心、異地數據中心。

這兩個概念也就是我上面說的同城雙活和異地多活的方式,只是針對的是數據中心。原理如下圖所示:

通過 B 站這件事情,我從中也學到了很多,本篇算是拋磚引玉,歡迎大家留言探討。

作者簡介:悟空,8年一線互聯網開發和架構經驗,用故事講解分佈式、架構設計、Java 核心技術。《JVM性能優化實戰》專欄作者,開源了《Spring Cloud 實戰 PassJava》項目,自主開發了一個 PMP 刷題小程序。

我是悟空,努力變強,變身超級賽亞人!

巨人的肩膀:

http://www.passjava.cn

https://cloud.tencent.com/developer/article/1618923

https://mp.weixin.qq.com/s/Vc4N5RcsN-K45o3VaRT4rA

https://time.geekbang.org/column/article/171115

https://time.geekbang.org/column/article/140763

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章