CAP原理

CAP原理(CAP THEOREM)
  在足球比賽裏,一個球員在一場比賽中進三個球,稱之爲帽子戲法(HAT-TRICK)。在分佈式數據系統中,也有一個帽子原理(CAP THEOREM),不過此帽子非彼帽子。CAP原理中,有三個要素:
  一致性(CONSISTENCY)可用性(AVAILABILITY)分區容忍性(PARTITION TOLERANCE)CAP原理指的是,這三個要素最多隻能同時實現兩點,不可能三者兼顧。因此在進行分佈式架構設計時,必須做出取捨。而對於分佈式數據系統,分區容忍性是基本要求,否則就失去了價值。因此設計分佈式數據系統,就是在一致性和可用性之間取一個平衡。對於大多數WEB應用,其實並不需要強一致性,因此犧牲一致性而換取高可用性,是目前多數分佈式數據庫產品的方向。
  當然,犧牲一致性,並不是完全不管數據的一致性,否則數據是混亂的,那麼系統可用性再高分佈式再好也沒有了價值。犧牲一致性,只是不再要求關係型數據庫中的強一致性,而是隻要系統能達到最終一致性即可,考慮到客戶體驗,這個最終一致的時間窗口,要儘可能的對用戶透明,也就是需要保障“用戶感知到的一致性”。通常是通過數據的多份異步複製來實現系統的高可用和數據的最終一致性的,“用戶感知到的一致性”的時間窗口則取決於數據複製到一致狀態的時間。
  最終一致性(EVENTUALLY CONSISTENT)
  對於一致性,可以分爲從客戶端和服務端兩個不同的視角。從客戶端來看,一致性主要指的是多併發訪問時更新過的數據如何獲取的問題。從服務端來看,則是更新如何複製分佈到整個系統,以保證數據最終一致。一致性是因爲有併發讀寫纔有的問題,因此在理解一致性的問題時,一定要注意結合考慮併發讀寫的場景。
  從客戶端角度,多進程併發訪問時,更新過的數據在不同進程如何獲取的不同策略,決定了不同的一致性。對於關係型數據庫,要求更新過的數據能被後續的訪問都能看到,這是強一致性。如果能容忍後續的部分或者全部訪問不到,則是弱一致性。如果經過一段時間後要求能訪問到更新後的數據,則是最終一致性。
  最終一致性根據更新數據後各進程訪問到數據的時間和方式的不同,又可以區分爲:
  因果一致性(CAUSAL CONSISTENCY)
  如果進程A通知進程B它已更新了一個數據項,那麼進程B的後續訪問將返回更新後的值,且一次寫入將保證取代前一次寫入。與進程A無因果關係的進程C的訪問遵守一般的最終一致性規則。“讀己之所寫(READ-YOUR-WRITES)”一致性。當進程A自己更新一個數據項之後,它總是訪問到更新過的值,絕不會看到舊值。這是因果一致性模型的一個特例。會話(SESSION)一致性。這是上一個模型的實用版本,它把訪問存儲系統的進程放到會話的上下文中。只要會話還存在,系統就保證“讀己之所寫”一致性。如果由於某些失敗情形令會話終止,就要建立新的會話,而且系統的保證不會延續到新的會話。單調(MONOTONIC)讀一致性。如果進程已經看到過數據對象的某個值,那麼任何後續訪問都不會返回在那個值之前的值。單調寫一致性。系統保證來自同一個進程的寫操作順序執行。要是系統不能保證這種程度的一致性,就非常難以編程了。上述最終一致性的不同方式可以進行組合,例如單調讀一致性和讀己之所寫一致性就可以組合實現。並且從實踐的角度來看,這兩者的組合,讀取自己更新的數據,和一旦讀取到最新的版本不會再讀取舊版本,對於此架構上的程序開發來說,會少很多額外的煩惱。
  從服務端角度,如何儘快將更新後的數據分佈到整個系統,降低達到最終一致性的時間窗口,是提高系統的可用度和用戶體驗非常重要的方面。對於分佈式數據系統:
  N — 數據複製的份數W — 更新數據是需要保證寫完成的節點數R — 讀取數據的時候需要讀取的節點數如果W+R>N,寫的節點和讀的節點重疊,則是強一致性。例如對於典型的一主一備同步複製的關係型數據庫,N=2,W=2,R=1,則不管讀的是主庫還是備庫的數據,都是一致的。
  如果W+R<=N,則是弱一致性。例如對於一主一備異步複製的關係型數據庫,N=2,W=1,R=1,則如果讀的是備庫,就可能無法讀取主庫已經更新過的數據,所以是弱一致性。
  對於分佈式系統,爲了保證高可用性,一般設置N>=3。不同的N,W,R組合,是在可用性和一致性之間取一個平衡,以適應不同的應用場景。
  如果N=W,R=1,任何一個寫節點失效,都會導致寫失敗,因此可用性會降低,但是由於數據分佈的N個節點是同步寫入的,因此可以保證強一致性。如果N=R,W=1,只需要一個節點寫入成功即可,寫性能和可用性都比較高。但是讀取其他節點的進程可能不能獲取更新後的數據,因此是弱一致性。這種情況下,如果W<(N+1)/2,並且寫入的節點不重疊的話,則會存在寫衝突

分佈式領域CAP理論,

Consistency(一致性), 數據一致更新,所有數據變動都是同步的
Availability(可用性), 好的響應性能
Partition tolerance(分區容錯性) 可靠性

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

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

BASE模型反ACID模型,完全不同ACID模型,犧牲高一致性,獲得可用性或可靠性:
Basically Available基本可用。支持分區失敗(e.g. sharding碎片劃分數據庫)
Soft state軟狀態 狀態可以有一段時間不同步,異步。
Eventually consistent最終一致,最終數據是一致的就可以了,而不是時時高一致。

BASE思想的主要實現有
1.按功能劃分數據庫
2.sharding碎片

BASE思想主要強調基本的可用性,如果你需要High 可用性,也就是純粹的高性能,那麼就要以一致性或容錯性爲犧牲,BASE思想的方案在性能上還是有潛力可挖的。

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

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

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

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