淺析分佈式一致性模型

轉載自:http://loopjump.com/distributed_consistency_model/

 

一致性術語的理解

一致性這個中文術語在計算機的不同領域有不同的含義,對應的英文術語也是不一樣的:Consistency, Consensus, Coherence等等。

就這三個術語而言,其區別可以簡單的如下理解:

  • Coherence這個單詞只在Cache Coherence場景下出現過,它關心的是多核共享內存的CPU架構下,各個核的Cache上數據如何保持一致。
  • Consensus是共識,它強調的是多個提議者就某件事情達成共識,可以說,我們關注的是達成共識的過程,例如Paxos協議,投票等。它是屬於replication protocol的範疇。
  • Consistency表達的含義相比就複雜一些:
    • 廣義上說,它描述了系統本身的不變量的維護程度對上層業務客戶端的影響,該系統併發的狀態的會暴露給客戶端什麼樣的異常行爲。CAP、ACID中的C都有這層意思。分佈式系統和數據庫分別獨立地使用了這個術語,我認爲也是基於這個術語本身的字面含義,因此將CAP的C和ACID的C視爲完全無關的極端看法也是失之片面的。
    • 但是,從狹義上說,ACID與CAP又有比較明顯的差別。CAP中C指的是多副本對外表現像單副本一樣,從任何一個副本讀取都會讀到最新的值,例如Dynamo的一致性弱於GFS的一致性(Dynamo是多個副本中一部分副本寫成功就對客戶端返回成功,而GFS是多個副本都寫成功了纔對客戶端返回成功)。而ACID中的C就不專門強調這個點下的含義,相反它更多表示數據庫內部數據的一致性,比如參照約束等。

不過Consistency含義比較複雜,一些理解也都有爭議,讀者如有不同看法,歡迎留言討論。

 

本文要說分佈式系統一致性模型,是指Consistency Model。實際上,Consistency Model的問題不只是出現在分佈式數據庫等這類分佈式系統,在多核下內存模型中也有類似的問題,或者說,這裏的分佈式系統是Lamport在分佈式時鐘事件序論文中描述的廣義的分佈式系統。有些一致性名字,如cache consistency,雖然是針對多核內存模型,但是同樣可以對應到分佈式存儲系統中來。

需要說明的是,本文描述的只是比較簡單的模型,即使在最近幾年,都一直有學術論文就其中某些一致性展開了進一步的研究。讀者如有更多相關資料,歡迎在評論中補充。如本文中描述有錯誤的地方,煩請讀者批評指出。

 

一致性模型

參考了若干材料,基本都是從兩個角度看一致性模型:data-centric consistency model和client-centric(user-centric) models。前者是從系統中數據的狀態角度出發探討一致性模型,後者是從client的角度出發探討的。我個人覺得前者會更重要一些,適用性也更廣泛一些,梳理起來難度也更大些。後者引入了session的概念,角度也有侷限。本文主要着眼於前者的解釋。

 

Data-Centric Consistency Models

 

1. Strict Consistency

任何讀操作都能讀取到最新的修改,換句話說,要求任何寫操作都立刻同步到其他所有進程。這裏強調的是絕對時鐘上的立刻同步,而任何信息的同步都需要延遲,因此在分佈式系統下無法嚴格實現。
不考慮系統的性能,一種可能的替代辦法就是:讓整個系統只在單個節點的單個線程運行。或者,在系統粒度上,讀寫操作操作被讀寫鎖保護起來(另一種形式的單點運行)。
strict

可以看到,在時間軸上,一旦有進程寫了x,則其他進程立刻就能讀到最新的值。

 

2. Sequential Consistency

Sequential Consistency摒棄了絕對時鐘的要求,而是使用分佈式邏輯時鐘。Sequential Consistency將所有事件定一個全序,且單個進程內的多個操作滿足program order,每個進程看到的都是這個全序。

Lamport給出了一種實現方式:首先,每個進程內的讀寫操作按順序issue;其次,每個進程的每個操作都被全局的一個FIFO隊列定序。在這種實現方式下,同一個進程的幾個操作在FIFO的順序一定是program order,不同進程的兩個操作順序是不確定的,可能違背兩個操作的絕對時間序。
sequential

如圖,w1,w2,w3實際發生順序是1<2<3,但是被定序後,可能是3<2<1。只要每個進程看到的定序結果是一致的,系統就是滿足Sequential Consistency的。

 

3. Linearizability (atomic consistency) & External Consistency

Linearizability比Sequential Consistency更嚴格。Linearizability在Sequential Consistency的約束基礎上,額外增加了如下的約束:如果操作A開始時間晚於B結束時間,則在Sequential Consistency定序時,要求B在A前。

直觀上,Linearizability要求的是,操作生效時間是在操作發起到操作返回之間的某個時刻。

External Consistency這個概念好像只有數據庫有(數據庫可以視爲多個併發事務操作共享的一組數據元素的分佈式系統),它的定義方式跟Serializable是相似的。Serializable定義的一個合法的全序同時滿足:各自事務內的讀寫操作的偏序、若干事務的偏序。External Consistency定義的一個合法全序同時滿足:各自事務內的讀寫操作的偏序、不同事務Begin和Commit事件產生的偏序。

如果一個事務T2的開始事件晚於T1的結束時間,那麼要求讀取時,要麼只讀取到T1的結果,要麼讀取到T1和T2的結果,不允許出現只讀取到T2的結果。在Google Spanner支持external consistency,感興趣的讀者可以參考Spanner解讀瞭解Spanner是如何實現支持這個一致性的。

查閱了若干資料均表示,External Consistency與Linearizability是等價的,只是使用的場景不一樣(注:Google在官方博客有段文字說明:Cloud Spanner provides external consistency, which is a stronger property than linearizability, because linearizability does not say anything about the behavior of transactions。我理解算是另外一種角度吧)。External Consistency名字是怎麼來的?我猜測:如果一個系統的通信完全只依賴系統內部數據的讀寫,那麼external consistency和sequential consistency是等價的。但是當系統的通信包括了外部的某些方式,即系統內部數據的關係實際還依賴系統外部定義的偏序關係,那麼,二者就不再等價,external consistency就能排除sequential consistency下產生的異常現象Anomalous Behaviour。我個人認爲,這個一致性可以視爲帶外部因果關係的sequential consistency。

Linearizability對於系統上層的業務來說,是很重要的。否則對於業務來說,就很難推斷系統狀態,比如我剛操作完數據d,然後把finish_flag標記爲true,如果不保證linearizability,其他讀者就無法依據finish_flag來安全地訪問數據d。

 

4. Causal Consistency

因果關係,就是Lamport在Lamport在分佈式時鐘事件序論文中描述的happen-before關係及其傳遞閉包,即如下三種因果:

  • 同一個進程內的事件A早於B (program order)
  • A完成後發消息通知觸發B
  • 已知A<B,B<C,根據傳遞性質推到出來的A<C

Causal Consistency要求,如果兩個事件有因果關係,則要求這兩個事件的先後順序滿足因果序,並且所有進程看到的這兩個事件的順序都是滿足這個因果序的。

Causal Consistency相比Sequential Consistency來說,僅要求有因果關係的事件順序對所有進程看到的一致,沒有因果關係的事件順序對於所有進程可以不一致。

casual

如圖示,P2把x從1改成2,因此讀取操作不允許出現R(x)2,R(x)1的現象。但是圖中,y操作沒有因果序,所以P3讀到R(y)2,R(y)1和P4讀到R(y)1,R(y)2的在Causal Consistency是允許的。這一現象,在Sequential Consistency是不允許的。不嚴格地說,Causal Consistency弱於Sequential Consistency。

 

5. FIFO Consistency (also known as PRAM consistency)

FIFO Consistency要求同一個進程的program order下的幾個操作被其他所有進程看到的順序是相同的。但是不同進程的幾個操作被其他所有進程看到的順序可能是不同的(即使有因果關係)。

fifo

6. Cache Consistency

FIFO Consistency要求同一個進程幾個操作被其他進程看到一致的順序。類似地, Cache Consistency要求所進程涉及到的同一個地址的幾個操作,要被所有進程看到一致的順序。FIFO Consistency和Cache Consistency相比,是兩個維度的約束,這兩個一致性是incomparable的。

cache

如圖,P3,P4看到的x,y分別是一致的。但是x,y並不是一致的。

 

7. Processor Consistency

processor

Processor Consistency是Cache Consistency + FIFO Consistency的結合,約束更多,因此這個一致性比另外兩個都更強。

 

8. Eventual Consistency

最終一致性:存儲系統保證如果沒有新的寫操作,那麼最終,所有的讀操作都能讀到一致的數據,這裏強調對一個數據項的修改最終會收斂。

這個一致性的概念也不是特別清晰,從1975年開始,不同時間段有不同研究者在定義使用,而且近幾年一直有人研究,感興趣的讀者可以參考http://www.bailis.org/這個教授的一些論文。

最終一致性在設計領域也有一些爭議,可以參考這裏http://queue.acm.org /detail.cfm?id=2610533。弱一致性確實帶給業務一些不方便,這可能也是近幾年強一致性的關係型數據庫又復甦的一個原因。

 

Client-Centric(User-Centric) Models

client-centric model,也叫user-centric model。在實際應用中,從分佈式系統的客戶端角度,對系統的讀寫操作通常都依賴session這樣的概念,session完全隸屬於某一個進程。該模型下有如下幾個一致性:Read Your Writes、Monotonic Reads、Monotonic Writes、Writs Follow Reads。

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