1. 程式人生 > >001-分布式理論-CAP定理

001-分布式理論-CAP定理

存儲系統 計時 來看 basic detail 正常的 容易 算法 state

一、概述

  CAP原則又稱CAP定理,指的是在一個分布式系統中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分區容錯性)這三個基本需求,最多只能同時滿足其中的2個。

  技術分享圖片

1、cap原則簡介

Consistency(一致性) 指數據在多個副本之間能夠保持一致的特性(嚴格的一致性)
Availability(可用性) 指系統提供的服務必須一直處於可用的狀態,每次請求都能獲取到非錯的響應(不保證獲取的數據為最新數據)
Partition tolerance(分區容錯性) 分布式系統在遇到任何網絡分區故障的時候,仍然能夠對外提供滿足一致性和可用性的服務,除非整個網絡環境都發生了故障

什麽是分區?

在分布式系統中,不同的節點分布在不同的子網絡中,由於一些特殊的原因,這些子節點之間出現了網絡不通的狀態,但他們的內部子網絡是正常的。從而導致了整個系統的環境被切分成了若幹個孤立的區域,這就是分區。

2、cap權衡

選 擇 說 明
CA 放棄分區容錯性,加強一致性和可用性,其實就是傳統的單機數據庫的選擇
AP 放棄一致性(這裏說的一致性是強一致性),追求分區容錯性和可用性,這是很多分布式系統設計時的選擇,例如很多NoSQL系統就是如此
CP 放棄可用性,追求一致性和分區容錯性,基本不會選擇,網絡問題會直接讓整個系統不可用

  對於一個分布式系統而言,分區容錯性是一個最基本的要求。因為 既然是一個分布式系統,那麽分布式系統中的組件必然需要被部署到不同的節點,否則也就無所謂分布式系統了,因此必然出現子網絡。而對於分布式系統而言,網 絡問題又是一個必定會出現的異常情況,因此分區容錯性也就成為了一個分布式系統必然需要面對和解決的問題。因此系統架構師往往需要把精力花在如何根據業務 特點在C(一致性)和A(可用性)之間尋求平衡。

  但是對於涉及到錢財這樣不能有一絲讓步的場景,C必須保證。網絡發生故障寧可停止服務,這是保證CA,舍棄P。還有一種是保證CP,舍棄A,例如網絡故障時只讀不寫。

二、起源

  在Towards Robust Distributed Systems 中,CAP理論的提出者Brewer指出:在分布式系統中,計算是相對容易的,真正困難的是狀態的維護。那麽對於分布式存儲或者說數據共享系統,數據的一致性保證也是比較困難的。對於傳統的關系型數據庫,優先考慮的是一致性而不是可用性,因此提出了事務的ACID特性。而對於許多分布式存儲系統,則是更看重可用性而不是一致性,一致性通過BASE(Basically Available, Soft state, Eventual consistency)來保證。下面這張圖展示了ACID與BASE的區別:

  技術分享圖片

  簡而言之:BASE通過最終一致性來盡量保證服務的可用性。註意圖中最後一句話“But I think it‘s a spectrum”,就是說ACID BASE只是一個度的問題,並不是對立的兩個極端。

  2002年,在Brewer‘s conjecture and the feasibility of consistent, available, partition-tolerant web services中,兩位作者通過異步網絡模型論證了CAP猜想,從而將Brewer的猜想升級成了理論(theorem)。但實話說,我也沒有把文章讀得很明白。

  2009年的這篇文章brewers-cap-theorem,作者給出了一個比較簡單的證明:

    技術分享圖片

  如上圖所示,N1,N2兩個節點存儲同一份數據V,當前的狀態是V0。在節點N1上運行的是安全可靠的寫算法A,在節點N2運行的是同樣可靠的讀算法B,即N1節點負責寫操作,N2節點負責讀操作。N1節點寫入的數據也會自動向N2同步,同步的消息稱之為M。如果N1,N2之間出現分區,那麽就沒法保證消息M在一定的時間內到達N2。

  從事務的角度來看這各問題

技術分享圖片

  α這個事務由操作α1, α2組成,其中α1是寫數據,α2是讀數據。如果是單點,那麽很容易保證α2能讀到α1寫入的數據。如果是分布式的情況的情況,除非能控制 α2的發生時間,否則無法保證 α2能讀到 α1寫入的數據,但任何的控制(比如阻塞,數據集中化等)要麽破壞了分區容錯性,要麽損失了可用性。

  另外,這邊文章指出很多情況下 availability比consistency重要,比如對於facebook google這樣的網站,短暫的不可用就會帶來巨大的損失。

  2010年的這篇文章brewers-cap-theorem-on-distributed-systems/,用了三個例子來闡述CAP,分別是example1:單點的mysql;example2:兩個mysql,但不同的mysql存儲不同的數據子集(類似sharding);example3:兩個mysql,對A的一個insert操作,需要在B上執行成功才認為操作完成(類似復制集)。作者認為在example1和example2上 都能保證強一致性,但不能保證可用性;在example3這個例子,由於分區(partition)的存在,就需要在一致性與可用性之間權衡。

  於我看來,討論CAP理論最好是在“分布式存儲系統”這個大前提下,可用性也不是說整體服務的可用性,而是分布式系統中某個子節點的可用性。因此感覺上文的例子並不是很恰當。

CAP理論發展

  到了2012年,CAP理論的發明人 Brewer就CAP理論再次撰文《CAP Twelve Years Later: How the "Rules" Have Changed》,這篇文章比較長,但思路清晰,高屋建瓴,非常值得一讀。網上也有對用的中文譯文《CAP理論十二年回顧:"規則"變了》,翻譯還不錯。   文章中,最主要的觀點是CAP理論並不是說三者不需選擇兩者。首先,雖然只要是分布式系統,就可能存在分區,但分區出現的概率是很小的(否則就需要去優化網絡或者硬件),CAP在大多數時候允許完美的C和A;只有在分區存在的時間段內,才需要在C與A之間權衡。其次,一致性和可用性都是一個度的問題,不是0或者1的問題,可用性可以在0%到100%之間連續變化,一致性分為很多級別(比如在casandra,可以設置consistency level)。因此,當代CAP實踐的目標應該是針對具體的應用,在合理範圍內最大化數據一致性和可用性的效力。   文章中還指出,分區是一個相對的概念,當超過了預定的通信時限,即系統如果不能在時限內達成數據一致性,就意味著發生了分區的情況,必須就當前操作在C和A之間做出選擇。
  從收入目標以及合約規定來講,系統可用性是首要目標,因而我們常規會使用緩存或者事後校核更新日誌來優化系統的可用性。因此,當設計師選擇可用性的時候,因為需要在分區結束後恢復被破壞的不變性約。   實踐中,大部分團體認為(位於單一地點的)數據中心內部是沒有分區的,因此在單一數據中心之內可以選擇CA;CAP理論出現之前,系統都默認這樣的設計思路,包括傳統數據庫在內。   分區期間,獨立且能自我保證一致性的節點子集合可以繼續執行操作,只是無法保證全局範圍的不變性約束不受破壞。數據分片(sharding)就是這樣的例子,設計師預先將數據劃分到不同的分區節點,分區期間單個數據分片多半可以繼續操作。相反,如果被分區的是內在關系密切的狀態,或者有某些全局性的不變性約束非保持不可,那麽最好的情況是只有分區一側可以進行操作,最壞情況是操作完全不能進行。

  上面摘錄中下選線部分跟MongoDB的sharding情況就很相似,MongoDB的sharded cluste模式下,shard之間在正常情況下,是無需相互通信的。

  在13年的文章中《better-explaining-cap-theorem》,作者指出“it is really just A vs C!”,因為

  (1)可用性一般是在不同的機器之間通過數據的復制來實現

  (2)一致性需要在允許讀操作之間同時更新幾個節點

  (3)temporary partion,即幾點之間的通信延遲是可能發生了,此時就需要在A 和 C之間權衡。但只有在發生分區的時候才需要考慮權衡。

  在分布式系統中,網絡分區一定會發生,因此“it is really just A vs C!”

參看地址:

  http://www.cnblogs.com/xybaby/p/6871764.html

  https://blog.csdn.net/baidu_22254181/article/details/84868709

  https://www.infoq.cn/article/cap-twelve-years-later-how-the-rules-have-changed

001-分布式理論-CAP定理