天天看點

從0開始學架構3 - 高可用篇

從0開始學架構.高可用篇

22 | 想成為架構師,你必須知道CAP理論

CAP 定理(CAP theorem)又被稱作布魯爾定理(Brewer’s theorem),是加州大學伯克利分校的計算機科學家埃裡克·布魯爾(Eric Brewer)在 2000 年的 ACM PODC 上提出的一個猜想。2002 年,麻省理工學院的賽斯·吉爾伯特(Seth Gilbert)和南希·林奇(Nancy Lynch)發表了布魯爾猜想的證明,使之成為分布式計算領域公認的一個定理。對于設計分布式系統的架構師來說,CAP 是必須掌握的理論。

CAP 理論
  • 一緻性(Consistency)。在事務執行過程中,系統其實處于一個不一緻的狀态,不同的節點的資料并不完全一緻。
  • 可用性(Availability)。注意沒有說“正确”的結果。隻要是合理的結果就可以。
  • 分區容忍性(Partition Tolerance)
CAP 應用

分布式系統理論上不可能選擇 CA 架構,隻能選擇 CP 或者 AP 架構。

  1. CP - Consistency/Partition Tolerance
從0開始學架構3 - 高可用篇
  1. AP - Availability/Partition Tolerance
從0開始學架構3 - 高可用篇

23 | 想成為架構師,你必須掌握的CAP細節

CAP 關鍵細節點
  • CAP 關注的粒度是資料,而不是整個系統。
  • CAP 是忽略網絡延遲的。
  • 正常運作情況下,不存在 CP 和 AP 的選擇,可以同時滿足 CA。
  • 放棄并不等于什麼都不做,需要為分區恢複後做準備。
ACID

ACID 是資料庫管理系統為了保證事務的正确性而提出來的一個理論,ACID 包含四個限制,下面我來解釋一下。

  • Atomicity(原子性)
  • Consistency(一緻性)
  • Isolation(隔離性)
  • Durability(持久性)
BASE

BASE 是指基本可用(Basically Available)、軟狀态( Soft State)、最終一緻性( Eventual Consistency),核心思想是即使無法做到強一緻性(CAP 的一緻性就是強一緻性),但應用可以采用适合的方式達到最終一緻性。

  • 基本可用(Basically Available)。分布式系統在出現故障時,允許損失部分可用性,即保證核心可用。
  • 軟狀态( Soft State)。允許系統存在中間狀态,而該中間狀态不會影響系統整體可用性。這裡的中間狀态就是 CAP 理論中的資料不一緻。
  • 最終一緻性( Eventual Consistency)。系統中的所有資料副本經過一定時間後,最終能夠達到一緻的狀态。例如,使用者看明星發的微網誌。

BASE 理論本質上是對 CAP 的延伸和補充,更具體地說,是對 CAP 中 AP 方案的一個補充。前面在剖析 CAP 理論時,提到了其實和 BASE 相關的兩點:

  • CAP 理論是忽略延時的,而實際應用中延時是無法避免的。
  • AP 方案中犧牲一緻性隻是指分區期間,而不是永遠放棄一緻性。
CAP & ACID & BASE

綜合上面的分析,ACID 是資料庫事務完整性的理論,CAP 是分布式系統設計理論,BASE 是 CAP 理論中 AP 方案的延伸。

24 | FMEA方法,排除架構可用性隐患的利器

FMEA 介紹

FMEA(Failure mode and effects analysis,故障模式與影響分析)

FMEA 方法

在架構設計領域,FMEA 的具體分析方法是:

  • 給出初始的架構設計圖。
  • 假設架構中某個部件發生故障。
  • 分析此故障對系統功能造成的影響。
  • 根據分析結果,判斷架構是否需要進行優化。

FMEA 分析的方法其實很簡單,就是一個 FMEA 分析表,常見的 FMEA 分析表格包含下面部分。

  • 功能點
  • 故障模式
  • 故障影響
  • 嚴重程度
  • 故障原因
  • 故障機率
  • 風險程度
  • 已有措施
  • 規避措施
  • 解決措施
  • 後續規劃
FMEA 實戰

下面我以一個簡單的樣例來模拟一次 FMEA 分析。假設我們設計一個最簡單的使用者管理系統,包含登入和注冊兩個功能,其初始架構是:

從0開始學架構3 - 高可用篇

初始架構很簡單:MySQL 負責存儲,Memcache(以下簡稱 MC)負責緩存,Server 負責業務處理。我們來看看這個架構通過 FMEA 分析後,能夠有什麼樣的發現,下表是分析的樣例(注意,這個樣例并不完整,感興趣的同學可以自行嘗試将這個案例補充完整)。

從0開始學架構3 - 高可用篇

經過上表的 FMEA 分析,将“後續規劃”列的内容彙總一下,我們最終得到了下面幾條需要改進的措施:

  • MySQL 增加備機。
  • MC 從單機擴充為叢集。
  • MySQL 雙網卡連接配接。

改進後的架構如下:

從0開始學架構3 - 高可用篇

25 | 高可用存儲架構:雙機架構

主備複制
從0開始學架構3 - 高可用篇

綜合主備複制架構的優缺點,内部的背景管理系統使用主備複制架構的情況會比較多,例如學生管理系統、員工管理系統、假期管理系統等,因為這類系統的資料變更頻率低,即使在某些場景下丢失資料,也可以通過人工的方式補全。

主從複制
從0開始學架構3 - 高可用篇

綜合主從複制的優缺點,一般情況下,寫少讀多的業務使用主從複制的存儲架構比較多。例如,論壇、BBS、新聞網站這類業務,此類業務的讀操作數量是寫操作數量的 10 倍甚至 100 倍以上。

雙機切換
  • 互連式

故名思議,互連式就是指主備機直接建立狀态傳遞的管道,架構圖請注意與主備複制架構對比。

從0開始學架構3 - 高可用篇
  • 中介式

中介式指的是在主備兩者之外引入第三方中介,主備機之間不直接連接配接,而都去連接配接中介,并且通過中介來傳遞狀态資訊,其架構圖如下:

從0開始學架構3 - 高可用篇

MongoDB 的 Replica Set 采取的就是這種方式,其基本架構如下:

從0開始學架構3 - 高可用篇

MongoDB(M) 表示主節點,MongoDB(S) 表示備節點,MongoDB(A) 表示仲裁節點。主備節點存儲資料,仲裁節點不存儲資料。用戶端同時連接配接主節點與備節點,不連接配接仲裁節點。

幸運的是,開源方案已經有比較成熟的中介式解決方案,例如 ZooKeeper 和 Keepalived。ZooKeeper 本身已經實作了高可用叢集架構,是以已經幫我們解決了中介本身的可靠性問題,在工程實踐中推薦基于 ZooKeeper 搭建中介式切換架構。

  • 模拟式

模拟式指主備機之間并不傳遞任何狀态資料,而是備機模拟成一個用戶端,向主機發起模拟的讀寫操作,根據讀寫操作的響應情況來判斷主機的狀态。其基本架構如下:

從0開始學架構3 - 高可用篇
主主複制

主主複制指的是兩台機器都是主機,互相将資料複制給對方,用戶端可以任意挑選其中一台機器進行讀寫操作,下面是基本架構圖。

從0開始學架構3 - 高可用篇

是以,主主複制架構對資料的設計有嚴格的要求,一般适合于那些臨時性、可丢失、可覆寫的資料場景。例如,使用者登入産生的 session 資料(可以重新登入生成)、使用者行為的日志資料(可以丢失)、論壇的草稿資料(可以丢失)等。

設計一個政府資訊公開網站的資訊存儲系統,你會采取哪種架構?談談你的分析和理由。

政府資訊網站使用主備或者主從架構就可以了。資訊都是人工錄入,可以補錄。資料本來對實時性要求不高,是以出了故障人工修複也來得及。是以主備就夠了,如果為了照顧形象可以用主從,保證主機故障後仍然可以查,不能新發

26 | 高可用存儲架構:叢集和分區

資料叢集
  • 資料集中叢集

資料集中叢集與主備、主從這類架構相似,我們也可以稱資料集中叢集為 1 主多備或者 1 主多從。無論是 1 主 1 從、1 主 1 備,還是 1 主多備、1 主多從,資料都隻能往主機中寫,而讀操作可以參考主備、主從架構進行靈活多變。下圖是讀寫全部到主機的一種架構:

從0開始學架構3 - 高可用篇

目前開源的資料集中叢集以 ZooKeeper 為典型,ZooKeeper 通過 ZAB 算法來解決上述提到的幾個問題,但 ZAB 算法的複雜度是很高的。

  • 資料分散叢集

資料分散叢集指多個伺服器組成一個叢集,每台伺服器都會負責存儲一部分資料;同時,為了提升硬體使用率,每台伺服器又會備份一部分資料。

資料分散叢集和資料集中叢集的不同點在于,資料分散叢集中的每台伺服器都可以處理讀寫請求,是以不存在資料集中叢集中負責寫的主機那樣的角色。但在資料分散叢集中,必須有一個角色來負責執行資料配置設定算法,這個角色可以是獨立的一台伺服器,也可以是叢集自己選舉出的一台伺服器。如果是叢集伺服器選舉出來一台機器承擔資料分區配置設定的職責,則這台伺服器一般也會叫作主機,但我們需要知道這裡的“主機”和資料集中叢集中的“主機”,其職責是有差異的。

Hadoop 的實作就是獨立的伺服器負責資料分區的配置設定,這台伺服器叫作 Namenode。Hadoop 的資料分區管理架構如下:

從0開始學架構3 - 高可用篇

與 Hadoop 不同的是,Elasticsearch 叢集通過選舉一台伺服器來做資料分區的配置設定,叫作 master node,其資料分區管理架構是:

從0開始學架構3 - 高可用篇

資料集中叢集架構中,用戶端隻能将資料寫到主機;資料分散叢集架構中,用戶端可以向任意伺服器中讀寫資料。正是因為這個關鍵的差異,決定了兩種叢集的應用場景不同。一般來說,資料集中叢集适合資料量不大,叢集機器數量不多的場景。例如,ZooKeeper 叢集,一般推薦 5 台機器左右,資料量是單台伺服器就能夠支撐;而資料分散叢集,由于其良好的可伸縮性,适合業務資料量巨大、叢集機器數量龐大的業務場景。例如,Hadoop 叢集、HBase 叢集,大規模的叢集可以達到上百台甚至上千台伺服器。

資料分區

設計一個良好的資料分區架構,需要從多方面去考慮。

  • 資料量
  • 分區規則
  • 複制規則。集中式、互備式和獨立式。

27 | 如何設計計算高可用架構?

計算高可用的主要設計目标是當出現部分硬體損壞時,計算任務能夠繼續正常運作。是以計算高可用的本質是通過備援來規避部分故障的風險,單台伺服器是無論如何都達不到這個目标的。是以計算高可用的設計思想很簡單:通過增加更多伺服器來達到計算高可用。

計算高可用架構的設計複雜度主要展現在任務管理方面,即當任務在某台伺服器上執行失敗後,如何将任務重新配置設定到新的伺服器進行執行。是以,計算高可用架構設計的關鍵點有下面兩點。

  • 哪些伺服器可以執行任務
  • 任務如何重新執行

接下來,我将詳細闡述常見的計算高可用架構:主備、主從和叢集。

主備

主備架構是計算高可用最簡單的架構,和存儲高可用的主備複制架構類似,但是要更簡單一些,因為計算高可用的主備架構無須資料複制,其基本的架構示意圖如下:

從0開始學架構3 - 高可用篇

根據備機狀态的不同,主備架構又可以細分為冷備架構和溫備架構。一般情況下推薦用溫備的方式。

和存儲高可用中的主備複制架構類似,計算高可用的主備架構也比較适合與内部管理系統、背景管理系統這類使用人數不多、使用頻率不高的業務,不太适合線上的業務。

主從

和存儲高可用中的主從複制架構類似,計算高可用的主從架構中的從機也是要執行任務的。任務配置設定器需要将任務進行分類,确定哪些任務可以發送給主機執行,哪些任務可以發送給備機執行,其基本的架構示意圖如下:

從0開始學架構3 - 高可用篇
叢集

主備架構和主從架構通過備援一台伺服器來提升可用性,且需要人工來切換主備或者主從。這樣的架構雖然簡單,但存在一個主要的問題:人工操作效率低、容易出錯、不能及時處理故障。是以在可用性要求更加嚴格的場景中,我們需要系統能夠自動完成切換操作,這就是高可用叢集方案。

高可用計算的叢集方案根據叢集中伺服器節點角色的不同,可以分為兩類:一類是對稱叢集,即叢集中每個伺服器的角色都是一樣的,都可以執行所有任務;另一類是非對稱叢集,叢集中的伺服器分為多個不同的角色,不同的角色執行不同的任務,例如最常見的 Master-Slave 角色。

  • 對稱叢集

對稱叢集更通俗的叫法是負載均衡叢集,是以接下來我使用“負載均衡叢集”這個通俗的說法,架構示意圖如下:

從0開始學架構3 - 高可用篇
  • 非對稱叢集

非對稱叢集中不同伺服器的角色是不同的,不同角色的伺服器承擔不同的職責。以 Master-Slave 為例,部分任務是 Master 伺服器才能執行,部分任務是 Slave 伺服器才能執行。非對稱叢集的基本架構示意圖如下:

從0開始學架構3 - 高可用篇
計算高可用架構從形式上和存儲高可用架構看上去幾乎一樣,它們的複雜度是一樣的麼?談談你的了解。

計算高可用架構,主要解決當單點發生故障後,原本發送到故障節點的任務,任務如何分發給非故障節點,根據業務特點選擇分發和重試機制即可,不存在資料一緻性問題,隻需要保證任務計算完成即可。

存儲高可用架構,解決的問題是當單點發生故障了,任務如何分發給其他非故障節點,以及如何保障資料的一緻性問題。

是以存儲的高可用比計算的高可用的設計更為複雜。

28 | 業務高可用的保障:異地多活架構

顧名思義,異地多活架構的關鍵點就是異地、多活,其中異地就是指地理位置上不同的地方,類似于“不要把雞蛋都放在同一籃子裡”;多活就是指不同地理位置上的系統都能夠提供業務服務,這裡的“活”是活動、活躍的意思。判斷一個系統是否符合異地多活,需要滿足兩個标準:

  • 正常情況下,使用者無論通路哪一個地點的業務系統,都能夠得到正确的業務服務。
  • 某個地方業務異常的時候,使用者通路其他地方正常的業務系統,能夠得到正确的業務服務。

是以,異地多活雖然功能很強大,但也不是每個業務不管三七二十一都要上異地多活。例如,常見的新聞網站、企業内部的 IT 系統、遊戲、部落格站點等,如果無法承受異地多活帶來的複雜度和成本,是可以不做異地多活的,隻需要做異地備份即可。因為這類業務系統即使中斷,對使用者的影響并不會很大,例如,A 新聞網站看不了,使用者換個新聞網站即可。而共享單車、滴滴出行、支付寶、微信這類業務,就需要做異地多活了,這類業務系統中斷後,對使用者的影響很大。例如,支付寶用不了,就沒法買東西了;滴滴用不了,使用者就打不到車了。

架構模式

根據地理位置上的距離來劃分,異地多活架構可以分為同城異區、跨城異地、跨國異地。

  • 同城異區

關鍵在于搭建高速網絡将兩個機房連接配接起來,達到近似一個本地機房的效果。架構設計上可以将兩個機房當作本地機房來設計,無須額外考慮。

  • 跨城異地

關鍵在于資料不一緻的情況下,業務不受影響或者影響很小,這從邏輯的角度上來說其實是沖突的,架構設計的主要目的就是為了解決這個沖突。

  • 跨國異地

主要是面向不同地區使用者提供業務,或者提供隻讀業務,對架構設計要求不高。

29 | 異地多活設計4大技巧

  • 技巧 1:保證核心業務的異地多活
  • 技巧 2:保證核心資料最終一緻性
  • 技巧 3:采用多種手段同步資料

綜合上述的各種措施,最後“使用者子系統”同步方式整體如下:

從0開始學架構3 - 高可用篇
  • 技巧 4:隻保證絕大部分使用者的異地多活
核心思想

異地多活設計的理念可以總結為一句話:采用多種手段,保證絕大部分使用者的核心業務異地多活!

30 | 異地多活設計4步走

今天,在掌握這 4 大技巧的基礎上,我來講講跨城異地多活架構設計的 4 個步驟。

  • 第 1 步:業務分級
  • 第 2 步:資料分類

我們同樣以使用者管理系統的登入業務為例,簡單分析如下表所示。

從0開始學架構3 - 高可用篇
  • 第 3 步:資料同步

我們同樣以使用者管理系統的登入業務為例,針對不同的資料特點設計不同的同步方案,如下表所示。

從0開始學架構3 - 高可用篇
  • 第 4 步:異常處理

常見的異常處理措施有這幾類:多通道同步、同步和通路結合、日志記錄、使用者補償

31 | 如何應對接口級的故障?

導緻接口級故障的原因一般有下面幾種:

  • 内部原因:程式 bug 導緻死循環,某個接口導緻資料庫慢查詢,程式邏輯不完善導緻耗盡記憶體等。
  • 外部原因:黑客攻擊、促銷或者搶購引入了超出平時幾倍甚至幾十倍的使用者,第三方系統大量請求,第三方系統響應緩慢等。

解決接口級故障的核心思想和異地多活基本類似:優先保證核心業務和優先保證絕大部分使用者。

降級

降級指系統将某些業務或者接口的功能降低,可以是隻提供部分功能,也可以是完全停掉所有功能。例如,論壇可以降級為隻能看文章,不能發文章;也可以降級為隻能看文章和評論,不能發評論;而 App 的日志上傳接口,可以完全停掉一段時間,這段時間内 App 都不能上傳日志。

降級的核心思想就是丢車保帥,優先保證核心業務。例如,對于論壇來說,90% 的流量是看文章,那我們就優先保證看帖的功能;對于一個 App 來說,日志上傳接口隻是一個輔助的功能,故障時完全可以停掉。

常見的實作降級的方式有:

  • 系統後門降級
  • 獨立降級系統
熔斷

熔斷和降級是兩個比較容易混淆的概念,因為單純從名字上看好像都有禁止某個功能的意思,但其實内在含義是不同的,原因在于降級的目的是應對系統自身的故障,而熔斷的目的是應對依賴的外部系統故障的情況。

熔斷機制實作的關鍵是需要有一個統一的 API 調用層,由 API 調用層來進行采樣或者統計,如果接口調用散落在代碼各處就沒法進行統一處理了。

熔斷機制實作的另外一個關鍵是門檻值的設計,例如 1 分鐘内 30% 的請求響應時間超過 1 秒就熔斷,這個政策中的“1 分鐘”“30%”“1 秒”都對最終的熔斷效果有影響。實踐中一般都是先根據分析确定門檻值,然後上線觀察效果,再進行調優。

限流

降級是從系統功能優先級的角度考慮如何應對故障,而限流則是從使用者通路壓力的角度來考慮如何應對故障。限流指隻允許系統能夠承受的通路量進來,超出系統通路能力的請求将被丢棄。

限流一般都是系統内實作的,常見的限流方式可以分為兩類:基于請求限流和基于資源限流。

  • 基于請求限流

基于請求限流指從外部通路的請求角度考慮限流,常見的方式有:限制總量、限制時間量。

限制總量的方式是限制某個名額的累積上限,常見的是限制目前系統服務的使用者總量,例如某個直播間限制總使用者數上限為 100 萬,超過 100 萬後新的使用者無法進入;某個搶購活動商品數量隻有 100 個,限制參與搶購的使用者上限為 1 萬個,1 萬以後的使用者直接拒絕。限制時間量指限制一段時間内某個名額的上限,例如,1 分鐘内隻允許 10000 個使用者通路,每秒請求峰值最高為 10 萬。

基于上述的分析,根據門檻值來限制通路量的方式更多的适應于業務功能比較簡單的系統,例如負載均衡系統、網關系統、搶購系統等。

  • 基于資源限流

基于請求限流是從系統外部考慮的,而基于資源限流是從系統内部考慮的,即:找到系統内部影響性能的關鍵資源,對其使用上限進行限制。常見的内部資源有:連接配接數、檔案句柄、線程數、請求隊列等。

例如,采用 Netty 來實作伺服器,每個進來的請求都先放入一個隊列,業務線程再從隊列讀取請求進行處理,隊列長度最大值為 10000,隊列滿了就拒絕後面的請求;也可以根據 CPU 的負載或者占用率進行限流,當 CPU 的占用率超過 80% 的時候就開始拒絕新的請求。

排隊

排隊實際上是限流的一個變種,限流是直接拒絕使用者,排隊是讓使用者等待一段時間,全世界最有名的排隊當屬 12306 網站排隊了。排隊雖然沒有直接拒絕使用者,但使用者等了很長時間後進入系統,體驗并不一定比限流好。

由于排隊需要臨時緩存大量的業務請求,單個系統内部無法緩存這麼多資料,一般情況下,排隊需要用獨立的系統去實作,例如使用 Kafka 這類消息隊列來緩存使用者請求。

下面是 1 号店的“雙 11”秒殺排隊系統架構

從0開始學架構3 - 高可用篇
  • 【排隊子產品】

負責接收使用者的搶購請求,将請求以先入先出的方式儲存下來。每一個參加秒殺活動的商品儲存一個隊列,隊列的大小可以根據參與秒殺的商品數量(或加點餘量)自行定義。

  • 【排程子產品】

負責排隊子產品到服務子產品的動态排程,不斷檢查服務子產品,一旦處理能力有空閑,就從排隊隊列頭上把使用者通路請求調入服務子產品,并負責向服務子產品分發請求。這裡排程子產品扮演一個中介的角色,但不隻是傳遞請求而已,它還擔負着調節系統處理能力的重任。我們可以根據服務子產品的實際處理能力,動态調節向排隊系統拉取請求的速度。

  • 【服務子產品】

負責調用真正業務來處理服務,并傳回處理結果,調用排隊子產品的接口回寫業務處理結果。

繼續閱讀