如何理解高可用架構設計原理

在分佈式系統中最重要的抽象概念之一是共識, 即在網絡、進程故障等情況下, 讓所有非故障節點在某一件事情上達成一致. 那麼在實現共識的過程中, 我們就需要在理論與實踐中去發現哪些可行, 哪些不可行. 對此我們需要了解什麼是分佈式一致性, 它和我們構建一個高可用系統架構有什麼關聯? 同樣今天來談談自己的思考.

高可用原理本質

一談到高可用架構設計, 想必我們都會想到採用 “冗餘” 來實現高可用. 即服務不可用, 增加冗餘服務; 節點不可用, 增加冗餘節點; 數據不可用, 增加冗餘數據副本. 這個時候我們的系統將由單體服務由於引入冗餘機制組成 “自己” 的集羣, 即:

從上述集羣架構中我們僅看到了多份相同的服務、節點和數據, 但是要實現高可用, 還需要一個關鍵能力, 即自動故障轉移.

什麼是自動故障轉移, 在上述的服務 / 節點集羣架構中, 我們試想下如果此時客戶端請求集羣服務, 那麼引入冗餘機制之後, 起初我們的架構如下:

從上述我們也很容看到, Client 是沒有感知到下游故障節點, 還是會將請求轉發到對應的故障節點中. 也就是我們 Client 如果能夠感知到下游節點的變化, 那麼我們 Client 就能夠進行決策, 不將請求轉發到故障節點上, 因此上述自動故障轉移其中一個關鍵因素就是狀態感知並決策的能力.

因此我們實現高可用架構的關鍵在於增加冗餘並實現自動故障轉移機制, 而實現自動故障轉移的核心是狀態感知並進行決策的能力, 也就是說我們集羣中的服務、節點以及數據需要通過協調彼此狀態來進行決策.

分佈式一致性與高可用狀態決策

既然我們知道自動故障轉移是依賴我們協調對應的節點來進行決策, 在前面我們講述過共識算法是一種通用有效保障的抽象, 因此我們這裏的共識算法就是實現一個狀態檢測與決策, 那麼基於上述的基礎上, 我們在冗餘的集羣引入共識算法來實現高可用, 這個時候我們的架構就會出現以下的演變方式, 即:

上述狀態決策是我們高可用架構狀態決策中常用的兩種方式, 即獨裁式以及民主狀態決策, 內部都是依託我們的共識算法來實現. 比如我們 Redis 的 Sentinel 哨兵機制就是獨裁式決策, 而 ZK 集羣則是民主式決策.

因此這個時候我們再來理解分佈式一致性的含義可能會更容易理解, 分佈式一致性就是協調各個節點的狀態以達成狀態決策的一致性, 而這個狀態主要有兩種, 其一是我們現在看到實現高可用需要感知到節點狀態並進行狀態的決策; 其二是對於數據存儲高可用服務, 還包含另外一個狀態, 即數據的一致性, 從而產生 CAP 以及 BASE 理論兩大框架來輔助我們如何就數據一致性進行架構設計與決策. 接下來我們再來看下數據層面的一致性設計.

強一致性與 CAP 定理

在存儲高可用架構中, 除了節點狀態的一致性, 同時還存在數據的一致性問題, 那麼數據一致性是怎麼產生的呢?

這裏我引用《設計數據密集系統》一書的一個例子, 假如先 Alice 以及 Bob 坐在同一個房間使用不同的手機查看足球世界盃, 這個時候世界公佈比分不久, Alice 刷新了頁面看到最新的公佈結果看到了公佈的獲勝方, 然後告訴了 Bob; 然而 Bob 刷新了自己手機的頁面卻一直沒有看到最新的結果, 這是爲什麼呢?

原來 Alice 的請求轉發的數據 follow1 的副本, 而 Bob 的請求卻給轉發到了 Follow2 的副本, 可以看到 Follow2 的副由於存在網絡延遲導致數據複製滯後, 而這段時間 Bob 看到的結果還是舊的一份數據, 即:

從上述可以看到我們設計數據存儲的高可用代價就是存在數據的一致性, 即 leader 節點將通過指定的複製方式發送複製數據格式到對應的數據副本節點上, 而數據一致性的產生正是由於複製過程中存在網絡延遲導致數據不一致.

那麼怎麼解決這個問題呢? 還是一樣利用共識算法來實現數據的一致性. 我們可以看到上述導致數據讀取不一致性根本原因是啥? 就是客戶端請求不知道當前數據存儲存儲到底哪一個數據副本節點是最新的, 這個時候我們同樣引入共識算法來協調存儲集羣內部當前最新數據狀態的副本有哪些並達成共識, 這個時候請求過來的時候先通過共識算法協調請求應該落到哪個節點能夠讀取最新的數據.

其實與前面處理節點的方式是類似的, 只不過這裏的 192.168.1.21 的節點並非是不可用節點, 而是數據不是最新節點, 如果採用左邊的架構方式, 那麼當 Client 請求 192.168.1.21 節點的時候就會將請求轉發到其他最新的節點上; 而如果是引入協調者, 那麼就不會將請求轉發到 192.168.1.21 節點上. 這個時候就是我們所說的線性一致性, 即強一致性模型.

在我們的 CAP 定理中的 C 就是強一致性模型, 相對於分佈式一致性, 它的範圍更小, 它主要是強調在非數據共享架構且存在數據複製的架構下, 如何協調數據最新狀態的一致性, 即讀己之所寫的一致性模型.CAP 是建立在 FLP 定理無網絡延遲的假設條件下, 闡述一致性、可用性以及分區容忍只能滿足其中兩個屬性.

從上述可以看出 CAP 忽略了實際網絡分區的存在, 而且如果我們用 CAP 來描述系統, 其實是不正確的, 因爲一個系統的數據可以是滿足 AP, 也可以是滿足 CP, CAP 關注的是單個數據, 並且是在非數據共享以及數據複製架構前提下去討論我們數據的一致性, 因此我們 CAP 的不可能三角以及對應的限定條件如下:

最終一致性與 BASE 理論

從上述的實現我們看到 192.168.1.21 這個節點其實並非故障, 但其實就是不能進行請求處理, 因爲我們要保證讀己之所寫的線性一致性而犧牲這個節點對外服務並存在浪費資源情況. 如果期間經過了時間 T,Bob 重新刷新頁面發現數據更新了, 那麼這個時候 Alice 以及 Bob 看到的頁面結果是一致, 只是存在時間差的問題, 一旦我們能夠容忍這種故障, 那麼 192.168.1.21 這個節點也將會加入服務提供列表中支持處理請求, 這個時候我們服務的可用性也將會提升, 即由原來的 2 臺提升至 3 臺並對外提供服務, 同樣也提升了資源利用率.

像上述的數據表現是允許短時間內出現數據不一致, 即混沌狀態, 但是經過一段時間之後, 我們的數據最終表現爲一致的, 我們稱之最終一致性. 對於最終一致性在分佈式系統中存在一個 BASE 理論, 是由 eBay 架構師 Dan Pritchett 於 2008 年提出, 作爲對 CAP 理論中的 AP 場景實踐的補充, 強調通過弱化一致性實現系統的高可用, 即:

BASE 理論含義:BASE 是 “Basically Available(基本可用)”、“Soft state(軟狀態)” 和“Eventually consistent(最終一致性)”三個短語的縮寫,由 eBay 架構師 Dan Pritchett 提出。核心思想即使無法做到強一致性, 但應用也能夠採用合適的方式達到最終一致性.

從這裏我們可以看出 BASE 理論是在我們 CAP 基礎上進行屬性弱化, 由 CAP 中的強一致性弱化爲最終一致性, 而可用性弱化爲基本可用, 對此我們可以將 CAP 以及 BASE 理論進行對比如下:

總結

至此我們已經對共識與 FLP 定理、CAP 定理以及 BASE 理論有了一個認知, 這裏我把之前的知識點串起來如下:

那麼當我們要進行高可用架構的時候, 如何運用上述來輔助我們進行架構落地呢? 這裏我總結並畫了張以供參考:

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/L3EjxFXtURg-ssY4TeVEvQ