分布式系统:一致性模型
分布式系統(tǒng)中一個重要的問題就是數(shù)據(jù)復制,數(shù)據(jù)復制一般是為了增強系統(tǒng)的可用性或提高性能。而實現(xiàn)數(shù)據(jù)復制的一個主要難題就是保持各個副本的一致性。本文首先討論數(shù)據(jù)復制的場景中一致性模型如此重要的原因,然后討論一致性模型的含義,最后分析常用的一致性模型。
為什么需要一致性模型
數(shù)據(jù)復制主要的目的有兩個:可用性和性能。首先數(shù)據(jù)復制可以提高系統(tǒng)的可用性。在保持多副本的情況,有一個副本不可用,系統(tǒng)切換到其他副本就會恢復。常用的 MySQL 主備同步方案就是一個典型的例子。另一方面,數(shù)據(jù)復制能夠提供系統(tǒng)的性能。當分布式系統(tǒng)需要在服務器數(shù)量和地理區(qū)域上進行擴展時,數(shù)據(jù)復制是一個相當重要的手段。有了多個數(shù)據(jù)副本,就能將請求分流;在多個區(qū)域提供服務時,也能通過就近原則提高客戶端訪問數(shù)據(jù)的效率。常用的 CDN 技術就是一個典型的例子。
但是數(shù)據(jù)復制是要付出代價的。數(shù)據(jù)復制帶來了多副本數(shù)據(jù)一致性的問題。一個副本的數(shù)據(jù)更新之后,其他副本必須要保持同步,否則數(shù)據(jù)不一致就可能導致業(yè)務出現(xiàn)問題。因此,每次更新數(shù)據(jù)對所有副本進行修改的時間以及方式?jīng)Q定了復制代價的大小。全局同步與性能實際上是矛盾的,而為了提高性能,往往會采用放寬一致性要求的方法。因此,我們需要用一致性模型來理解和推理在分布式系統(tǒng)中數(shù)據(jù)復制需要考慮的問題和基本假設。
什么是一致性模型
首先我們要定義一下一致性模型的術語:
下面是一致性模型的定義:
一致性模型本質上是進程與數(shù)據(jù)存儲的約定:如果進程遵循某些規(guī)則,那么進程對數(shù)據(jù)的讀寫操作都是可預期的。
上面的定義可能比較抽象,我們用常見的強一致性模型來通俗的解釋一下:在線性一致性模型中,進程對一個數(shù)據(jù)項的讀操作,它期待數(shù)據(jù)存儲返回的是該數(shù)據(jù)在最后一次寫操作之后的結果。這在單機系統(tǒng)里面很容易實現(xiàn),在 MySQL 中只要使用加鎖讀的方式就能保證讀取到數(shù)據(jù)在最后一次寫操作之后的結果。但在分布式系統(tǒng)中,因為沒有全局時鐘,導致要精確定義哪次寫操作是最后一次寫操作是非常困難的事情,因此產(chǎn)生了一系列的一致性模型。每種模型都有效限制了在對一個數(shù)據(jù)項執(zhí)行讀操作所應該返回的值。舉個例子:假設記錄值 X 在節(jié)點 M 和 N 上都有副本,當客戶端 A 修改了副本 M 上 X 的值,一段時間之后,客戶端 B 從 N 上讀取 X 的值,此時一致性模型會決定客戶端 B 是否能夠讀取到 A 寫入的值。
一致性模型主要可以分為兩類:能夠保證所有進程對數(shù)據(jù)的讀寫順序都保持一致的一致性模型稱為強一致性模型,而不能保證的一致性模型稱為弱一致性模型。
強一致性模型
線性一致性(Linearizable Consistency)
線性一致性也叫嚴格一致性(Strict Consistency)或者原子一致性(Atomic Consistency),它的條件是:
線性一致性是對一致性要求最高的一致性模型,就現(xiàn)有技術是不可能實現(xiàn)的。因為它要求所有操作都實時同步,在分布式系統(tǒng)中要做到全局完全一致時鐘現(xiàn)有技術是做不到的。首先通信是必然有延遲的,一旦有延遲,時鐘的同步就沒法做到一致。當然不排除以后新的技術能夠做到,但目前而言線性一致性是無法實現(xiàn)的。
順序一致性(Sequential Consistency)
順序一致性是 Lamport(1979)在解決多處理器系統(tǒng)共享存儲器時首次提出來的。參考我之前寫的文章《分布式系統(tǒng):Lamport 邏輯時鐘》。它的條件是:
首先我們先來分析一下線性一致性和順序一致性的相同點在哪里。他們都能夠保證所有進程對數(shù)據(jù)的讀寫順序保持一致。線性一致性的實現(xiàn)很簡單,就按照全局時鐘(可以簡單理解為物理時鐘)為參考系,所有進程都按照全局時鐘的時間戳來區(qū)分事件的先后,那么必然所有進程看到的數(shù)據(jù)讀寫操作順序一定是一樣的,因為它們的參考系是一樣的。而順序一致性使用的是邏輯時鐘來作為分布式系統(tǒng)中的全局時鐘,進而所有進程也有了一個統(tǒng)一的參考系對讀寫操作進行排序,因此所有進程看到的數(shù)據(jù)讀寫操作順序也是一樣的。
那么線性一致性和順序一致性的區(qū)別在哪里呢?通過上面的分析可以發(fā)現(xiàn),順序一致性雖然通過邏輯時鐘保證所有進程保持一致的讀寫操作順序,但這些讀寫操作的順序跟實際上發(fā)生的順序并不一定一致。而線性一致性是嚴格保證跟實際發(fā)生的順序一致的。
弱一致性模型
因果一致性(Causal Consistency)
因果一致性是一種弱化的順序一致性模型,因為它將具有潛在因果關系的事件和沒有因果關系的事件區(qū)分開了。那么什么是因果關系?如果事件 B 是由事件 A 引起的或者受事件 A 的影響,那么這兩個事件就具有因果關系。
舉個分布式數(shù)據(jù)庫的示例,假設進程 P1 對數(shù)據(jù)項 x 進行了寫操作,然后進程 P2 先讀取了 x,然后對 y 進行了寫操作,那么對 x 的讀操作和對 y 的寫操作就具有潛在的因果關系,因為 y 的計算可能依賴于 P2 讀取到 x 的值(也就是 P1 寫的值)。
另一方面,如果兩個進程同時對兩個不同的數(shù)據(jù)項進行寫操作,那么這兩個事件就不具備因果關系。無因果關系的操作稱為并發(fā)操作。這里只是簡單陳述了一下,深入的分析見我之前寫的文章《分布式系統(tǒng):向量時鐘》。
因果一致性的條件包括:
下面我們來分析一下為什么說因果一致性是一種弱化的順序一致性模型。順序一致性雖然不保證事件發(fā)生的順序跟實際發(fā)生的保持一致,但是它能夠保證所有進程看到的讀寫操作順序是一樣的。而因果一致性更進一步弱化了順序一致性中對讀寫操作順序的約束,僅保證有因果關系的讀寫操作有序,沒有因果關系的讀寫操作(并發(fā)事件)則不做保證。也就是說如果是無因果關系的數(shù)據(jù)操作不同進程看到的值是有可能是不一樣,而有因果關系的數(shù)據(jù)操作不同進程看到的值保證是一樣的。
最終一致性(Eventual Consistency)
最終一致性是更加弱化的一致性模型,因果一致性起碼還保證了有因果關系的數(shù)據(jù)不同進程讀取到的值保證是一樣的,而最終一致性只保證所有副本的數(shù)據(jù)最終在某個時刻會保持一致。
從某種意義上講,最終一致性保證的數(shù)據(jù)在某個時刻會最終保持一致就像是在說:“人總有一天會死”一樣。實際上我們更加關心的是:
由于最終一致性對數(shù)據(jù)一致性的要求比較低,在對性能要求高的場景中是經(jīng)常使用的一致性模型。
以客戶端為中心的一致性(Client-centric Consistency)
前面我們討論的一致性模型都是針對數(shù)據(jù)存儲的多副本之間如何做到一致性,考慮這么一種場景:在最終一致性的模型中,如果客戶端在數(shù)據(jù)不同步的時間窗口內訪問不同的副本的同一個數(shù)據(jù),會出現(xiàn)讀取同一個數(shù)據(jù)卻得到不同的值的情況。為了解決這個問題,有人提出了以客戶端為中心的一致性模型。以客戶端為中心的一致性為單一客戶端提供一致性保證,保證該客戶端對數(shù)據(jù)存儲的訪問的一致性,但是它不為不同客戶端的并發(fā)訪問提供任何一致性保證。
舉個例子:客戶端 A 在副本 M 上讀取 x 的最新值為 1,假設副本 M 掛了,客戶端 A 連接到副本 N 上,此時副本 N 上面的 x 值為舊版本的 0,那么一致性模型會保證客戶端 A 讀取到的 x 的值為 1,而不是舊版本的 0。一種可行的方案就是給數(shù)據(jù) x 加版本標記,同時客戶端 A 會緩存 x 的值,通過比較版本來識別數(shù)據(jù)的新舊,保證客戶端不會讀取到舊的值。
以客戶端為中心的一致性包含了四種子模型:
總結
數(shù)據(jù)復制導致了一致性的問題,為了保持副本的一致性可能會嚴重地影響性能,唯一的解決辦法就是放松一致性的要求。通過一致性模型我們可以理解和推理在分布式系統(tǒng)中數(shù)據(jù)復制需要考慮的問題和基本假設,便于結合具體的業(yè)務場景做權衡。每種模型都有效地限制了對一個數(shù)據(jù)項執(zhí)行度操作應返回的值。通常來說限制越少的模型越容易應用,但一致性的保證就越弱。
原文鏈接
本文為云棲社區(qū)原創(chuàng)內容,未經(jīng)允許不得轉載。
總結
以上是生活随笔為你收集整理的分布式系统:一致性模型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 阿里云物联网边缘计算加载MQTT驱动
- 下一篇: java信息管理系统总结_java实现科