CAP理論以及Eventually Consistent (最終一致性)解析

xmuzyu發表於2010-01-17
1 CAP理論簡介

10年前,Eric Brewer教授指出了著名的CAP理論,後來Seth Gilbert 和 Nancy lynch兩人證明了CAP理論的正確性。CAP(Consistency,Availability,partition tolerance)理論告訴我們,一個分散式系統不可能滿足一致性,可用性和分割槽容錯性這三個需求,最多隻能同時滿足兩個(至於CAP理論的證明,可以參考附件的論文)。

在CAP理論的指導下,架構師或者開發者應該清楚,您當前架構和設計的系統真正的需求是什麼?您的系統到底是關注的是可用性還是一致性的需求。如果您的系統關注的是一致性,那麼您就需要處理因為系統不可用而導致的寫操作失敗的情況,而如果您關注的是可用性,那麼您應該知道系統的read操作可能不能精確的讀取到write操作寫入的最新值。因此係統的關注點不同,相應的採用的策略也是不一樣的,只有真正的理解了系統的需求,才有可能利用好CAP理論。

2 一致性

說起一致性,我們有兩種視角去看待它,第一種是客戶或者開發者視角,此種情況下,客戶或者開發者更加關注:如何觀察到系統的更新,另外一種視覺是伺服器端視覺,此種情況下,主要關注:更新操作如何flow through系統以及系統對更新操作提供什麼樣子的一致性保證。

下面就分別從這兩種角度去看看一致性:

2.1 客戶端一致性

為了更好的描述客戶端一致性,我們透過以下的場景來進行,這個場景中包括三個組成部分:

儲存系統

儲存系統可以理解為一個黑盒子,它為我們提供了可用性和永續性的保證。

Process A

ProcessA主要實現從儲存系統write和read操作

Process B 和ProcessC

ProcessB和C是獨立於A,並且B和C也相互獨立的,它們同時也實現對儲存系統的write和read操作。

下面以上面的場景來描述下不同程度的一致性:

強一致性(即時一致性)

假如A先寫入了一個值到儲存系統,儲存系統保證後續A,B,C的讀取操作都將返回最新值

弱一致性

假如A先寫入了一個值到儲存系統,儲存系統不能保證後續A,B,C的讀取操作能讀取到最新值。此種情況下有一個“不一致性視窗”的概念,它特指從A寫入值,到後續操作A,B,C讀取到最新值這一段時間。

最終一致性

最終一致性是弱一致性的一種特例。假如A首先write了一個值到儲存系統,儲存系統保證如果在A,B,C後續讀取之前沒有其它寫操作更新同樣的值的話,最終所有的讀取操作都會讀取到最A寫入的最新值。此種情況下,如果沒有失敗發生的話,“不一致性視窗”的大小依賴於以下的幾個因素:互動延遲,系統的負載,以及複製技術中replica的個數(這個可以理解為master/salve模式中,salve的個數),最終一致性方面最出名的系統可以說是DNS系統,當更新一個域名的IP以後,根據配置策略以及快取控制策略的不同,最終所有的客戶都會看到最新的值。

其中最終一致性(Eventually consistency)還有以下幾個變體,下面分別描述:

Causal consistency(因果一致性):如果Process A通知Process B它已經更新了資料,那麼Process B的後續讀取操作則讀取到A寫入的最新值,而與A沒有因果關係的C則採用最終一致性的語義。

Read-your-writes consistency:如果Process A寫入了最新的值,那麼Process A的後續操作都會讀取到最新值。比如以本論壇為例,當某使用者發表一個帖子以後,該使用者可以立即看到自己發表的帖子,但是其它使用者可能要過一會才可以看到,這就是典型的Read-your-writer-consistency。


Session consistency:此種一致性要求客戶端和儲存系統互動的整個會話階段保證Read-your-writes consistency.Hibernate的session提供的一致性保證就屬於此種一致性。

Monotonic read consistency:此種一致性要求如果Process A已經讀取了物件的某個值,那麼後續操作將不會讀取到更早的值。

Monotonic write consistency:此種一致性保證系統會序列化執行一個Process中的所有寫操作。


2.1 伺服器端一致性

在說伺服器端一致性要求,我們首先要明確幾個概念:
N: 節點的總個數
W 更新的時候需要確認已經被更新的節點的個數
R: 讀取資料的時候讀取資料的節點個數

如果W+R>N,那麼分散式系統就會提供強一致性的保證,因為讀取資料的節點和被同步寫入的節點是有重疊的。在一個RDBMS的複製模型中(Master/salve),假如N=2,那麼W=2,R=1此時是一種強一致性,但是這樣造成的問題就是可用性的減低,因為要想寫操作成功,必須要等2個節點都完成以後才可以。

在分散式系統中,一般都要有容錯性,因此一般N都是大於3的,此時根據CAP理論,一致性,可用性和分割槽容錯性最多隻能滿足兩個,那麼我們就需要在一致性和分割槽容錯性之間做一平衡,如果要高的一致性,那麼就配置N=W,R=1,這個時候可用性就會大大降低。如果想要高的可用性,那麼此時就需要放鬆一致性的要求,此時可以配置W=1,這樣使得寫操作延遲最低,同時透過非同步的機制更新剩餘的N-W個節點。

當儲存系統保證最終一致性時,儲存系統的配置一般是W+R<=N,此時讀取和寫入操作是不重疊的,不一致性的視窗就依賴於儲存系統的非同步實現方式,不一致性的視窗大小也就等於從更新開始到所有的節點都非同步更新完成之間的時間。

無論是Read-your-writes-consistency,Session consistency,Monotonic read consistency,它們都透過黏貼(stickiness)客戶端到執行分散式請求的伺服器端來實現的,這種方式簡單是簡單,但是它使得負載均衡以及分割槽容錯變的更加難於管理,有時候也可以透過客戶端來實現Read-your-writes-consistency和Monotonic read consistency,此時需要對寫的操作的資料加版本號,這樣客戶端就可以遺棄版本號小於最近看到的版本號的資料。

在系統開發過程中,根據CAP理論,可用性和一致性在一個大型分割槽容錯的系統中只能滿足一個,因此為了高可用性,我們必須放低一致性的要求,但是不同的系統保證的一致性還是有差別的,這就要求開發者要清楚自己用的系統提供什麼樣子的最終一致性的保證,一個非常流行的例子就是web應用系統,在大多數的web應用系統中都有“使用者可感知一致性”的概念,這也就是說最終一致性中的“一致性視窗"大小要小於使用者下一次的請求,在下次讀取操作來之前,資料可以在儲存的各個節點之間複製。還比如假如儲存系統提供了read-your-write-consistency一致性,那麼當一個使用者寫操作完成以後可以立馬看到自己的更新,但是其它的使用者要過一會才可以看到更新。

以上是這篇文章核心的總結:

Eventually Consistency

相關文章