1. 程式人生 > >分散式系統的一致性級別劃分及Zookeeper一致性級別分析

分散式系統的一致性級別劃分及Zookeeper一致性級別分析

最近在研究分散式系統的一些理論概念,例如關於分散式系統一致性的討論,看了一些文章我有一些不解。大多數對分散式系統一致性的劃分是將其分為三類:強一致性,順序一致性以及弱一致性。強一致性(Strict Consistency)也稱為:原子一致性(Atomic Consistency)、線性一致性(Linearizable Consistency)。

在談到Zookeeper的一致性是哪種級別的一致性問題,以及CAP原則中的C是哪一種一致性級別時有些疑惑。

下面是大多數文章中提到的一致性級別

1. 一致性(Consistency)

一致性(Consistency)是指多副本(Replications)問題中的資料一致性。可以分為強一致性、順序一致性與弱一致性。

1.1 強一致性(Strict Consistency)

也稱為:原子一致性(Atomic Consistency)線性一致性(Linearizable Consistency)

強一致性有兩個要求:

  • 任何一次讀都能讀到某個資料的最近一次寫的資料。
  • 系統中的所有程序,看到的操作順序,都和全域性時鐘下的順序一致。

簡言之,在任意時刻,所有節點中的資料都是一樣的。

例如,對於關係型資料庫,要求更新過的資料能被後續的訪問都能看到,這是強一致性。

1.2 順序一致性(Sequential Consistency)

the result of any execution is the same as if the operations of all the processors were executed in some sequential order, and the operations of each individual processor appear in this sequence in the order specified by its program. - - Lamport

兩個要求:

  • 任何一次讀都能讀到某個資料的最近一次寫的資料。
  • 系統的所有程序的順序一致,而且是合理的。即不需要和全域性時鐘下的順序一致,錯的話一起錯,對的話一起對。

舉個例子:

Write(x, 4):寫入x=4
Read(x, 0):讀出x=0

1)圖a是滿足順序一致性,但是不滿足強一致性的。原因在於,從全域性時鐘的觀點來看,P2程序對變數X的讀操作在P1程序對變數X的寫操作之後,然而讀出來的卻是舊的資料。但是這個圖卻是滿足順序一致性的,因為兩個程序P1,P2的一致性並沒有衝突。從這兩個程序的角度來看,順序應該是這樣的:Write(y,2) , Read(x,0) , Write(x,4), Read(y,2),每個程序內部的讀寫順序都是合理的,但是這個順序與全域性時鐘下看到的順序並不一樣。

2)圖b滿足強一致性,因為每個讀操作都讀到了該變數的最新寫的結果,同時兩個程序看到的操作順序與全域性時鐘的順序一樣,都是Write(y,2) ,Write(x,4), Read(x,4) ,  Read(y,2)。

3)圖c不滿足順序一致性,當然也就不滿足強一致性了。因為從程序P1的角度看,它對變數Y的讀操作返回了結果0。那麼就是說,P1程序的對變數Y的讀操作在P2程序對變數Y的寫操作之前,這意味著它認為的順序是這樣的:Write(x,4) , Read(y,0) , Write(y,2), Read(x,0),顯然這個順序又是不能被滿足的,因為最後一個對變數x的讀操作讀出來也是舊的資料。因此這個順序是有衝突的,不滿足順序一致性。

1.3 弱一致性

資料更新後,如果能容忍後續的訪問只能訪問到部分或者全部訪問不到,則是弱一致性。

最終一致性就屬於弱一致性。

最終一致性

不保證在任意時刻任意節點上的同一份資料都是相同的,但是隨著時間的遷移,不同節點上的同一份資料總是在向趨同的方向變化。

簡單說,就是在一段時間後,節點間的資料會最終達到一致狀態。

最終一致性根據更新資料後各程序訪問到資料的時間和方式的不同,又可以區分為:

因果一致性(Casual Consistency)。如果程序A通知程序B它已更新了一個數據項,那麼程序B的後續訪問將返回更新後的值,且一次寫入將保證取代前一次寫入。與程序A無因果關係的程序C的訪問,遵守一般的最終一致性規則。

“讀己之所寫(read-your-writes)”一致性。當程序A自己更新一個數據項之後,它總是訪問到更新過的值,絕不會看到舊值。這是因果一致性模型的一個特例。

會話(Session)一致性。這是上一個模型的實用版本,它把訪問儲存系統的程序放到會話的上下文中。只要會話還存在,系統就保證“讀己之所寫”一致性。如果由於某些失敗情形令會話終止,就要建立新的會話,而且系統的保證不會延續到新的會話。

單調(Monotonic)讀一致性。如果程序已經看到過資料物件的某個值,那麼任何後續訪問都不會返回在那個值之前的值。

單調寫一致性。系統保證來自同一個程序的寫操作順序執行。要是系統不能保證這種程度的一致性,就非常難以程式設計了。


 

另外一種劃分一致性級別的:

一致性是指從系統外部讀取系統內部的資料時,在一定約束條件下相同,即資料變動在系統內部各節點應該是同步的。根據一致性的強弱程度不同,可以將一致性級別分為如下幾種:

  ①強一致性(strong consistency)。任何時刻,任何使用者都能讀取到最近一次成功更新的資料。
  ②單調一致性(monotonic consistency)。任何時刻,任何使用者一旦讀到某個資料在某次更新後的值,那麼就不會再讀到比這個值更舊的值。也就是說,獲取的資料順序必是單調遞增的。
  ③會話一致性(session consistency)。任何使用者在某次會話中,一旦讀到某個資料在某次更新後的值,那麼在本次會話中就不會再讀到比這值更舊的值。會話一致性是在單調一致性的基礎上進一步放鬆約束,只保證單個使用者單個會話內的單調性,在不同使用者或同一使用者不同會話間則沒有保障。示例case:php的session概念。
  ④ 最終一致性(eventual consistency)。使用者只能讀到某次更新後的值,但系統保證資料將最終達到完全一致的狀態,只是所需時間不能保障。
  ⑤弱一致性(weak consistency)。使用者無法在確定時間內讀到最新更新的值。

2. 共識(Consensus)

共識問題中所有的節點要最終達成共識,由於最終目標是所有節點都要達成一致,所以根本不存在一致性強弱之分。

例如,Paxos是共識(Consensus)演算法而不是強一致性(Consistency)協議。共識演算法沒有一致性級別的區分。


疑惑

關於線性一致性的觀點,《線性一致性(Linearizability)是併發控制的基礎》中提到,Zookeeper是線性一致性的,再比如分散式領域著名的CAP定理中的C,也是指線性一致性。

在《如何理解Zookeeper的順序一致性》中闡述的觀點是Zookeeper是順序一致性的,不是最終一致性也不是強一致性。

又有人在某文章下評論說順序一致性和最終一致性不是同一個維度的概念。

3.線性化和可序列化的區別

另外在一篇英文文章《Linearizability versus Serializability》講述了線性化和可序列化的區別

Linearizability for read and write operations is synonymous with the term “atomic consistency” and is the “C,” or “consistency,” in Gilbert and Lynch’s proof of the CAP Theorem. We say linearizability is composable (or “local”) because, if operations on each object in a system are linearizable, then all operations in the system are linearizable.

翻譯:讀寫操作的線性化與術語“原子一致性”同義,並且是Gilbert和Lynch 對CAP定理的證明中的 “C”或“一致性” 。我們說線性化是可組合的 (或“本地”),因為如果系統中每個物件的操作是可線性化的,那麼系統中的所有操作都是可線性化的。

Serializability is the traditional “I,” or isolation, in ACID. If users’ transactions each preserve application correctness (“C,” or consistency, in ACID), a serializable execution also preserves correctness. Therefore, serializability is a mechanism for guaranteeing database correctness.1

 

Unlike linearizability, serializability does not—by itself—impose any real-time constraints on the ordering of transactions. Serializability is also not composable. Serializability does not imply any kind of deterministic order—it simply requires that some equivalent serial execution exists.

翻譯:可序列性是ACID中的傳統“I”或隔離。如果使用者的事務各自保持應用程式的正確性(ACID中的“C”或一致性),則可序列化執行也保持正確性。因此,可序列化是一種保證資料庫正確性的機制。

與線性化不同,可序列化本身不會對事務的排序施加任何實時約束。可序列化也是不可組合的。可序列化並不意味著任何型別的確定性順序 - 它只需要存在一些等效的序列執行。

One of the reasons these definitions are so confusing is that linearizability hails from the distributed systems and concurrent programming communities, and serializability comes from the database community. Today, almost everyone uses both distributed systems and databases, which often leads to overloaded terminology (e.g., “consistency,” “atomicity”).

翻譯:這些定義如此混亂的原因之一是線性化來自分散式系統和併發程式設計社群,可序列化來自資料庫社群。如今,幾乎每個人都使用分散式系統和資料庫,這往往會導致過載的術語(例如,“一致性”,“原子”)。

4、zookeeper的一致性分析-單調一致性

很多文章和部落格裡提到,zookeeper是一種提供強一致性的服務,在分割槽容錯性和可用性上做了一定折中,這和CAP理論是吻合的。但實際上Zookeeper提供的只是單調一致性。
原因:
  1. 假設有2n+1個server,在同步流程中,leader向follower同步資料,當同步完成的follower數量大於 n+1時同步流程結束,系統可接受client的連線請求。如果client連線的並非同步完成的follower,那麼得到的並非最新資料,但可以保證單調性,也就是說,可獲取的資料順序是單調遞增的。
  2. 假設是follower接收到的寫請求,則會轉發給leader處理;leader完成兩階段提交的機制。向所有server發起提案,當提案獲得超過半數(n+1)的server的ACK後,將對整個叢集進行同步,超過半數(n+1)的server同步完成後,該寫請求完成。如果client連線的並非同步完成follower,那麼得到的並非最新資料,但可以保證單調性,也就是說,可獲取的資料順序是單調遞增的。

用分散式系統的CAP原則來分析Zookeeper:
(1)C: Zookeeper保證了最終一致性,在十幾秒可以Sync到各個節點
(2)A: Zookeeper保證了可用性,資料總是可用的,沒有鎖.並且有一大半的節點所擁有的資料是最新的,實時的. 如果想保證取得是資料一定是最新的,需要手工呼叫Sync()
(3)P: 有2點需要分析的

  • 節點多了會導致寫資料延時非常大,因為需要多個節點同步.
  • 節點多了Leader選舉非常耗時, 就會放大網路的問題. 可以通過引入 observer節點緩解這個問題.

5、 結論

可以的出的結論是Zookeeper的一致性保證的是單調一致性,CAP原則中的C是強一致性。

———————————————— 

參考:https://blog.csdn.net/chao2016/article/details/81149674

https://www.cnblogs.com/sunddenly/articles/4072987.html

http://www.bailis.org/blog/linearizability-versus-serializabil