- 鳳凰架構:構建可靠的大型分布式系統
- 周志明
- 2935字
- 2021-06-24 11:30:56
3.4.1 CAP與ACID
CAP定理(Consistency、Availability、Partition Tolerance Theorem),也稱為Brewer定理,起源于2000年7月,是加州大學伯克利分校的Eric Brewer教授于“ACM分布式計算原理研討會(PODC)”上提出的一個猜想,如圖3-5所示。

圖3-5 CAP理論原稿(那時候還只是猜想)[1]
兩年后,麻省理工學院的Seth Gilbert和Nancy Lynch以嚴謹的數學推理證明了CAP猜想。自此,CAP正式從猜想變為分布式計算領域所公認的著名定理。這個定理描述了在一個分布式系統中,涉及共享數據問題時,以下三個特性最多只能同時滿足其中兩個。
·一致性(Consistency):代表數據在任何時刻、任何分布式節點中所看到的都是符合預期的。一致性在分布式研究中是有嚴肅定義、有多種細分類型的概念,以后討論分布式共識算法時,我們還會提到一致性,但那種面向副本復制的一致性與這里面向數據庫狀態的一致性從嚴格意義來說并不完全等同,具體差別我們將在第6章再作探討。
·可用性(Availability):代表系統不間斷地提供服務的能力。理解可用性要先理解與其密切相關的兩個指標:可靠性(Reliability)和可維護性(Serviceability)。可靠性使用平均無故障時間(Mean Time Between Failure,MTBF)來度量;可維護性使用平均可修復時間(Mean Time To Repair,MTTR)來度量。可用性衡量系統可以正常使用的時間與總時間之比,其表征為:A=MTBF/(MTBF+MTTR),即可用性是由可靠性和可維護性計算得出的比例值,譬如99.9999%可用,即代表平均年故障修復時間為32秒。
·分區容忍性(Partition Tolerance):代表分布式環境中部分節點因網絡原因而彼此失聯后,即與其他節點形成“網絡分區”時,系統仍能正確地提供服務的能力。
單純只列概念,CAP是比較抽象的,筆者仍以本章開頭所列的場景事例來說明這三種特性對分布式系統來說將意味著什么。假設Fenix’s Bookstore的服務拓撲如圖3-6所示,一個來自最終用戶的交易請求,將交由賬號、商家和倉庫服務集群中的某一個節點來完成響應。

圖3-6 Fenix’s Bookstore的服務拓撲示意圖
在這套系統中,每一個單獨的服務節點都有自己的數據庫[2],假設某次交易請求分別由“賬號節點1”“商家節點2”“倉庫節點N”聯合進行響應。當用戶購買一件價值100元的商品后,賬號節點1首先應給該用戶賬號扣減100元貨款,它在自己數據庫扣減100元很容易,但它還要把這次交易變動告知本集群的節點2到節點N,并要確保能正確變更商家和倉庫集群其他賬號節點中的關聯數據,此時將可能面臨以下情況。
·如果該變動信息沒有及時同步給其他賬號節點,將有可能導致用戶購買另一商品時,被分配給另一個節點處理,由于看到賬號上有不正確的余額而錯誤地發生了原本無法進行的交易,此為一致性問題。
·如果由于要把該變動信息同步給其他賬號節點,必須暫時停止對該用戶的交易服務,直至數據同步一致后再重新恢復,將可能導致用戶在下一次購買商品時,因系統暫時無法提供服務而被拒絕交易,此為可用性問題。
·如果由于賬號服務集群中某一部分節點因網絡問題,無法正常與另一部分節點交換賬號變動信息,此時服務集群中無論哪一部分節點對外提供的服務都可能是不正確的。整個集群不能承受由于部分節點之間的連接中斷而不斷繼續正確地提供服務,此為分區容忍性問題。
以上僅僅分析了用戶服務集群自身的CAP問題,對于整個Fenix’s Bookstore站點來說,它更是面臨著來自于用戶、商家和倉庫服務集群帶來的CAP問題。譬如,用戶賬號扣款后,由于未及時通知倉庫服務中的全部節點,導致另一次交易中看到倉庫里有不正確的庫存數據而發生超售。又譬如因涉及倉庫中某個商品的交易正在進行,為了同步用戶、商家和倉庫的交易變動,而暫時鎖定該商品的交易服務,導致可用性問題,等等。
由于CAP定理已有嚴格的證明,本節不去探討為何CAP不可兼得,而是直接分析舍棄C、A、P時所帶來的不同影響。
·如果放棄分區容忍性(CA without P),意味著我們將假設節點之間的通信永遠是可靠的。永遠可靠的通信在分布式系統中必定是不成立的,這不是你想不想的問題,而是只要用到網絡來共享數據,分區現象就始終存在。在現實中,最容易找到放棄分區容忍性的例子便是傳統的關系數據庫集群,這樣的集群雖然依然采用由網絡連接的多個節點來協同工作,但數據卻不是通過網絡來實現共享的。以Oracle的RAC集群為例,它的每一個節點均有自己獨立的SGA、重做日志、回滾日志等部件,但各個節點是通過共享存儲中的同一份數據文件和控制文件來獲取數據,通過共享磁盤的方式來避免出現網絡分區。因而Oracle RAC雖然也是由多個實例組成的數據庫,但它并不能稱作分布式數據庫。
·如果放棄可用性(CP without A),意味著我們將假設一旦網絡發生分區,節點之間的信息同步時間可以無限制地延長,此時,問題相當于退化到前面3.2節討論的一個系統使用多個數據源的場景之中,我們可以通過2PC/3PC等手段,同時獲得分區容忍性和一致性。在現實中,選擇放棄可用性的情況一般出現在對數據質量要求很高的場合中,除了DTP模型的分布式數據庫事務外,著名的HBase也屬于CP系統。以HBase集群為例,假如某個RegionServer宕機了,這個RegionServer持有的所有鍵值范圍都將離線,直到數據恢復過程完成為止,這個過程要消耗的時間是無法預先估計的。
·如果放棄一致性(AP without C),意味著我們將假設一旦發生分區,節點之間所提供的數據可能不一致。選擇放棄一致性的AP系統是目前設計分布式系統的主流選擇,因為P是分布式網絡的天然屬性,你再不想要也無法丟棄;而A通常是建設分布式的目的,如果可用性隨著節點數量增加反而降低的話,很多分布式系統可能就失去了存在的價值,除非銀行、證券這些涉及金錢交易的服務,寧可中斷也不能出錯,否則多數系統是不能容忍節點越多可用性反而越低的。目前大多數NoSQL庫和支持分布式的緩存框架都是AP系統,以Redis集群為例,如果某個Redis節點出現網絡分區,那仍不妨礙各個節點以自己本地存儲的數據對外提供緩存服務,但這時有可能出現請求分配到不同節點時返回客戶端的是不一致的數據的情況。
讀到這里,不知道你是否對“選擇放棄一致性的AP系統是目前設計分布式系統的主流選擇”這個結論感到一絲無奈,本章討論的話題“事務”原本的目的就是獲得“一致性”,而在分布式環境中,“一致性”卻不得不成為通常被犧牲、被放棄的那一項屬性。但無論如何,我們建設信息系統,終究還是要確保操作結果至少在最終交付的時候是正確的,這句話的意思是允許數據在中間過程出錯(不一致),但應該在輸出時被修正過來。為此,人們又重新給一致性下了定義,將前面我們在CAP、ACID中討論的一致性稱為“強一致性”(Strong Consistency),有時也稱為“線性一致性”(Linearizability,通常是在討論共識算法的場景中),而把犧牲了C的AP系統又要盡可能獲得正確結果的行為稱為追求“弱一致性”。不過,如果單純只說“弱一致性”那其實就是“不保證一致性”的意思。在弱一致性里,人們又總結出了一種稍微強一點的特例,被稱為“最終一致性”(Eventual Consistency),它是指如果數據在一段時間之內沒有被另外的操作更改,那它最終會達到與強一致性過程相同的結果,有時候面向最終一致性的算法也被稱為“樂觀復制算法”。
在本節討論的主題“分布式事務”中,目標同樣也不得不從之前三種事務模式追求的強一致性,降低為追求獲得“最終一致性”。由于一致性的定義變動,“事務”一詞的含義其實也同樣被拓展了,人們把使用ACID的事務稱為“剛性事務”,而把筆者下面將要介紹的幾種分布式事務的常見做法統稱為“柔性事務”。
[1] 圖片來源:https://people.eecs.berkeley.edu/~brewer/cs262b-2004/PODC-keynote.pdf。
[2] 這里的假設是為了便于說明問題,在實際生產系統中,一般應避免將用戶余額這樣的數據存儲在多個可寫的數據庫中。
- Linux網絡管理與配置(第2版)
- Red Hat Enterprise Linux 8系統管理實戰
- 發布!設計與部署穩定的分布式系統(第2版)
- PLC控制系統應用與維護
- Ubuntu Linux操作系統
- Installing and Configuring Windows 10:70-698 Exam Guide
- Extending Bootstrap
- 嵌入式Linux應用開發菜鳥進階
- Linux運維最佳實踐
- 8051軟核處理器設計實戰
- 嵌入式系統原理及開發
- STM32庫開發實戰指南:基于STM32F4
- Joomla! 3 Template Essentials
- OpenStack系統架構設計實戰
- 深入淺出Node.js