CAP、ACID、BASE理論及NWR實踐策略詳解

一、分佈式領域CAP理論,
Consistency(一致性), 保證獲得的都是完成狀態的數據,不然直接失敗。

Availability(可用性), 在容忍的響應時間內,每一個操做老是可以返回,不會出現所謂in_flight IO,老是能及時響應。

Partition tolerance(分區容忍性) 可以保證系統是分區的。(原文是:No set of failures less than total network failure is allowed to cause the system to respond incorrectly),比較難理解,簡單的解釋一下這是個反證,除非整個分佈式系統所在的網絡都掛掉,不然只要還有分區就能給出正確響應。


定理:任何分佈式系統只可同時知足二點,無法三者兼顧。
注意:架構師不要將精力浪費在如何設計能知足三者的完美分佈式系統,而是應該進行取捨。


二、關係型數據庫ACID模型:
關係數據庫的ACID模型擁有 高一致性 + 可用性 可是很難知足分區容忍性:
Atomicity 原子性:一個事務中全部操做都必須所有完成,要麼所有不完成。
Consistency 一致性. 在事務開始或結束時,數據庫應該在一致狀態。
Isolation 隔離性. 事務將假定只有它本身在操做數據庫,彼此不知曉。
Durability 持久性. 一旦事務完成,就不能返回。
跨數據庫事務:2PC (two-phase commit), 2PC is the anti-scalability pattern (Pat Helland) 是反可伸縮模式的,JavaEE中的JTA事務能夠支持2PC。由於2PC是反模式,儘可能不要使用2PC,使用BASE來回避。


3. BASE理論

eBay的架構師Dan Pritchett源於對大規模分佈式系統的實踐總結,在ACM上發表文章提出BASE理論,BASE理論是對CAP理論的延伸,核心思想是即便沒法作到強一致性(Strong Consistency,CAP的一致性就是強一致性),但應用能夠採用適合的方式達到最終一致性(Eventual Consitency)。 mysql

BASE是指基本可用(Basically Available)、軟狀態( Soft State)、最終一致性( Eventual Consistency)。 sql

基本可用(Basically Available)
基本可用是指分佈式系統在出現故障的時候,容許損失部分可用性,即保證核心可用。

電商大促時,爲了應對訪問量激增,部分用戶可能會被引導到降級頁面,服務層也可能只提供降級服務。這就是損失部分可用性的體現。 數據庫

 軟狀態( Soft State)

軟狀態是指容許系統存在中間狀態,而該中間狀態不會影響系統總體可用性。分佈式存儲中通常一份數據至少會有三個副本,容許不一樣節點間副本同步的延時就是軟狀態的體現。mysql replication的異步複製也是一種體現。 swift

 最終一致性( Eventual Consistency)
最終一致性是指系統中的全部數據副本通過必定時間後,最終可以達到一致的狀態。弱一致性和強一致性相反,最終一致性是弱一致性的一種特殊狀況。

4. ACID和BASE的區別與聯繫

ACID是傳統數據庫經常使用的設計理念,追求強一致性模型。BASE支持的是大型分佈式系統,提出經過犧牲強一致性得到高可用性。 緩存

ACID和BASE表明了兩種截然相反的設計哲學 網絡

在分佈式系統設計的場景中,系統組件對一致性要求是不一樣的,所以ACID和BASE又會結合使用。 架構


BASE思想主要強調基本的可用性,若是你須要High 可用性,也就是純粹的高性能,那麼就要以一致性或分區容忍性爲犧牲,BASE思想的方案在性能上仍是有潛力可挖的。

如今NoSQL
運動豐富了拓展了BASE思想,可按照具體狀況定製特別方案,好比忽視一致性,得到高可用性等等,NOSQL應該有下面兩個流派:
1. Key-Value存儲,如Amaze Dynamo等,可根據CAP三原則靈活選擇不一樣傾向的數據庫產品。
2. 領域模型 + 分佈式緩存 + 存儲 (Qi4j和NoSQL運動),可根據CAP三原則結合本身項目定製靈活的分佈式方案,難度高。

這二者共同點:都是關係數據庫SQL之外的可選方案,邏輯隨着數據分佈,任何模型均可以本身持久化,將數據處理和數據存儲分離,將讀和寫分離,存儲能夠是異步或同步,取決於對一致性的要求程度。

不一樣點:NOSQL之類的Key-Value存儲產品是和關係數據庫頭碰頭的產品BOX,能夠適合非Java如PHP RUBY等領域,是一種能夠拿來就用的產品,而領域模型 + 分佈式緩存 + 存儲是一種複雜的架構解決方案,不是產品,但這種方式更靈活,更應該是架構師必須掌握的。

五、NWR是CAP理論的一個具體實踐性的取捨策略: 併發


  Amazon寫了個論文,描述了一下若是取捨的具體策略,具體到副本數怎麼設定,這就是NWR。 less


  N = 副本數 異步

  W = 一次成功的寫操做必須完成的寫副本數

  R = 一次成功的讀操做須要讀的副本數(是的,隨便讀一個副本是不行的,你必須讀到必定數量的副本,再相互比較取最新的數據)


策略來講就有具體的公式可供運算,有兩個:

 

  W > N/2

  W + R > N 


咱們結合Swift的設定,N=3,W=2,R=2(or 1),來看看這兩個公式是什麼意義。


分佈式系統一般用來處理大併發請求的應用,不少請求你們同時來,有一堆在讀,也有一堆想寫。

假設有一個數據擁有三副本,每一個副本已經同步好,原來的值都是A


咱們看看若是不須要知足公式讓W小於3/2,也就是W=1的狀況下會出現什麼問題,W=1,意味着每一個寫的請求只要寫完一個副本便可成功返回。


假設兩個進程同時來更新這份數據,進程W1要把值改寫成C,進程W2要把值改寫成B,那就有可能出現下圖的情形,兩個進程各拿到一個副本改寫,都認爲本身的寫操做是成功的,結果卻留給系統三個不一樣的副本,這樣就出現數據副本不一致的問題。

Swift裏的CAP理論和NWR策略應用

  因此公式W> N/2, 實際上變成了一個寫的鎖,意味着只有寫了過半數副本的纔算寫成功,拿不到的就返回失敗,解決了競爭的問題。以下圖,W1的會話成功,W2的會話就返回失敗。

Swift裏的CAP理論和NWR策略應用

  W> N/2,同時意味着不須要把全部的副本都寫完,未完成的留給系統本身後臺慢慢同步,那這個時候問題就來了,一個新的會話過來讀數據的時候,分配到的副本有多是沒來得及更新的。這時候R1讀回去的就是過期的數據B,而非最新的數據C

Swift裏的CAP理論和NWR策略應用

 第2個公式變形下就是R> N-W,R=2就避免正好倒黴讀到沒更新的那一個。這樣讀回去C和B兩個數據,再比較後取最新的C。因此W+R> N 可以保證每一個讀的請求至少讀到一份最新的數據,

Swift裏的CAP理論和NWR策略應用 


    因此你也許已經琢磨出來,這兩個公式更增強調一致性,在可用性上是有所保留的。


固然NWR還可能取其餘值,不一樣的取值表明了不一樣的傾向。若是設定N=3, W=3, R=1,那麼強調的是一致性,寫數據的時候必定要把全部副本都刷新,杜絕中間狀態,這樣一致性獲得很好保證;若是N=3, W=1, R=1,那強調的是可用性,這種狀況下一致性是被犧牲掉了,因此上面兩個保證一致性的公式在這種狀況下就再也不適用。之因此可用性提升是由於讀和寫都放低了要求,只要完成一個副本便可,這樣完成時間下降,響應速度是更快的。


N=3, W=2, R=2是一種折中的策略。其實Amazon的Dynamo就是採用的這個參數,聽說Swift是照搬S3的。 

  因此回到Swift的副本設定來看,swift的NWR值是可調的,有兩種配置,一種是標準的N3W2R2,可是實際上你也可使用N3W2R1,這個更實用點。在這種配置下,雖然一個數據擁有三副本,可是容錯上讀寫是不同的。網絡斷線,硬盤故障等意外形成一個副本失效時, 系統仍然可讀可寫,但兩個副本失效時,受影響的這部分數據系統就變成只讀,沒法再寫了。


CAP理論和NWR策略在大規模系統下是比較合理的,除了被用來設計分佈式存儲以外,也用來設計分佈式數據庫,好比很熱的NOSQL。另外,這個理論問世已經不短的時間,也常常看到有人發文要挑戰他,也有一些吐槽等等,那個是另外的話題,這裏就再也不繼續了。


六、總結NWR:

R>N/2:表示一次讀操做成功,必須是完成超過半數以上的副本讀操做(否則有可能讀到不一致數據或者出現問題無法根據票數多來進行選舉)

R>N-W:表示一次成功的讀操做,至少要完成超過全部副本數N減去全部寫成功W份數的差值。這樣即能保證每一個讀請求至少可以讀到一份最新數據。


N=3,W=3,R=1:總共副本數爲3,強調了寫的強一致性,寫數據的時候必定要把全部副本刷新才能算寫成功,杜絕中間狀態,這樣一致性達到了很好的保證。

N=3,W=1,R=1:總共副本數爲3,這樣一致性犧牲了,由於讀寫都放低了要求,因此提升了系統可用性。

swift及Amazon採用的默認策略:

N=3, W=2, R=2:這樣保證了每次讀寫必須完成半數以上副本才能算成功,算是折中方案。

相關文章
相關標籤/搜索