1. 程式人生 > >深入解析:分散式系統的事務處理經典問題及模型(轉載分享)

深入解析:分散式系統的事務處理經典問題及模型(轉載分享)

編者按:資料服務的高可用是所有企業都想擁有的,但是要想讓資料有高可用性,就需要冗餘資料寫多份。寫多份的問題會帶來一致性的問題,而一致性的問題又會帶來效能問題,這就會陷入一個無解的死迴圈!這裡所謂資料一致性,就是當多個使用者試圖同時訪問一個數據庫時,如果它們的事務同時使用相同的資料,可能會發生以下四種情況:丟失更新、未確定的相關性、不一致的分析和幻像讀。本篇文章將會給大家系統的介紹多種處理分散式資料一致性的技術模型,以下是作者原文:

在生產線上用一臺伺服器來提供資料服務的時候,經常會遇到如下的兩個問題:

  • 一臺伺服器的效能不足以提供足夠的能力服務於所有網路請求。
  • 擔心伺服器宕機,造成服務不可用或是資料丟失。

面對這些問題,我們不得不對伺服器進行擴充套件,加入更多的機器來分擔效能問題,以及解決單點故障問題。通常,我們會通過兩種手段來擴充套件我們的資料服務:

  • 資料分割槽:就是把資料分塊放在不同的伺服器上(如:uid % 16,一致性雜湊等)。
  • 資料映象:讓所有的伺服器資料同步,提供無差別的資料服務。

使用第一種方案,無法解決資料丟失問題,單臺伺服器出問題時,一定會有部分資料丟失。所以,資料服務的高可用性只能通過第二種方法來完成——資料的冗餘儲存(一般工業界認為比較安全的備份數應該是3份,如:Hadoop和Dynamo)。 但是,加入的機器越多資料就會變得越複雜,尤其是跨伺服器的事務處理,也就是跨伺服器的資料一致性。這個是一個很難的問題!讓我們用最經典的Use Case:“A帳號向B帳號匯錢”來說明一下,熟悉RDBMS事務的都知道從帳號A到帳號B需要6個操作:

  1. 從A帳號中把餘額讀出來;
  2. 對A帳號做減法操作;
  3. 把結果寫回A帳號中;
  4. 從B帳號中把餘額讀出來;
  5. 對B帳號做加法操作;
  6.  把結果寫回B帳號中。

為了資料的一致性,這6件事,要麼都成功做完,要麼都不成功,而且這個操作的過程中,對A、B帳號的其它訪問必需鎖死,所謂鎖死就是要排除其它的讀寫操作,不然會有髒資料問題,這就是事務。但是,在加入了多個機器後,這個事情會變得複雜起來:

  1. 在資料分割槽的方案中:如果A帳號和B帳號的資料不在同一臺伺服器上怎麼辦?我們需要一個跨機器的事務處理。也就是說,如果A的扣錢成功了,但B的加錢不成功,我們還要把A的操作給回滾回去。在不同的機器上實現,就會比較複雜。
  2. 在資料映象的方案中:
    A帳號和B帳號間的匯款是可以在一臺機器上完成的,但是別忘了我們有多臺機器存在A帳號和B帳號的副本。如果對A帳號的匯錢有兩個併發操作(要匯給B和C),這兩個操作發生在不同的兩臺伺服器上怎麼辦?也就是說,在資料映象中,在不同的伺服器上對同一個資料的寫操作怎麼保證其一致性,保證資料不衝突?

同時,我們還要考慮效能因素,如果不考慮效能的話,事務完成並不困難,系統慢一點就行了。除了考慮效能外,我們還要考慮可用性,也就是說,一臺機器沒了,資料不丟失,服務可由別的機器繼續提供。 於是,我們需要重點考慮下面的這麼幾個情況:

  • 容災:資料不丟、結點的Failover
  • 資料的一致性:事務處理
  • 效能:吞吐量 、 響應時間

前面說過,要解決資料不丟,只能通過資料冗餘的方法,就算是資料分割槽,每個區也需要進行資料冗餘處理。這就是資料副本:當出現某個節點的資料丟失時可以從副本讀到,資料副本是分散式系統解決資料丟失異常的唯一手段。所以,在這篇文章中,我們只討論在資料冗餘情況下考慮資料的一致性和效能的問題。簡單說來:

  • 要想讓資料有高可用性,就得寫多份資料。
  • 寫多份的問題會導致資料一致性的問題。
  • 資料一致性的問題又會引發效能問題

這就是軟體開發,按下了葫蘆起了瓢。

一致性模型

說起資料一致性來說,簡單說有三種類型(當然,如果細分的話,還有很多一致性模型,如:順序一致性,FIFO一致性,會話一致性,單讀一致性,單寫一致性,但為了本文的簡單易讀,我只說下面三種):

  1. Weak 弱一致性:當你寫入一個新值後,讀操作在資料副本上可能讀出來,也可能讀不出來。比如:某些cache系統,網路遊戲其它玩家的資料和你沒什麼關係,VOIP這樣的系統,或是百度搜索引擎。
  2. Eventually 最終一致性:當你寫入一個新值後,有可能讀不出來,但在某個時間視窗之後保證最終能讀出來。比如:DNS,電子郵件、Amazon S3,Google搜尋引擎這樣的系統。
  3. Strong 強一致性:新的資料一旦寫入,在任意副本任意時刻都能讀到新值。比如:檔案系統,RDBMS,Azure Table都是強一致性的。

從這三種一致型的模型上來說,我們可以看到,Weak和Eventually一般來說是非同步冗餘的,而Strong一般來說是同步冗餘的,非同步的通常意味著更好的效能,但也意味著更復雜的狀態控制;同步意味著簡單,但也意味著效能下降。讓我們由淺入深,一步一步地來看有哪些技術:

Master-Slave

首先是Master-Slave結構,對於這種加構,Slave一般是Master的備份。在這樣的系統中,一般是如下設計的:

  • 讀寫請求都由Master負責。
  • 寫請求寫到Master上後,由Master同步到Slave上。

從Master同步到Slave上,可以使用非同步,也可以使用同步,可以使用Master來push,也可以使用Slave來pull。 通常來說是Slave來週期性的pull,所以是最終一致性。這個設計的問題是,如果Master在pull週期內垮掉了,那麼會導致這個時間片內的資料丟失。如果你不想讓資料丟掉,Slave只能成為Read-Only的方式等Master恢復。

當然,如果可以容忍資料丟掉的話,可以馬上讓Slave代替Master工作(對於只負責計算的結點來說,沒有資料一致性和資料丟失的問題,Master-Slave的方式就可以解決單點問題了) 當然,Master Slave也可以是強一致性的, 比如:當寫Master的時候,Master負責先備份,等成功後,再寫Slave,兩者都成功後返回成功,整個過程是同步的,如果寫Slave失敗了,那麼兩種方法,一種是標記Slave不可用報錯並繼續服務(等Slave恢復後同步Master的資料,可以有多個Slave,這樣少一個,還有備份,就像前面說的寫三份那樣),另一種是回滾自己並返回寫失敗。(注:一般不先寫Slave,因為如果寫Master自己失敗後,還要回滾Slave,此時如果回滾Slave失敗,就得手工訂正資料了)可以看到,如果Master-Slave需要做成強一致性有多複雜。

Master-Master

Master-Master,又叫Multi-master,是指一個系統存在兩個或多個Master,每個Master都提供read-write服務。這個模型是Master-Slave加強版,資料間同步一般是通過Master間非同步完成,所以是最終一致性。 Master-Master的好處是一臺Master掛了,別的Master可以正常做讀寫服務,這個和Master-Slave一樣,當資料沒有被複制到別的Master上時資料會丟失。很多資料庫都支援Master-Master的Replication的機制。

另外,如果多個Master對同一個資料進行修改的時候,這個模型的惡夢就出現了——需要對資料間的衝突進行合併,這非常困難。看看Dynamo的Vector Clock的設計(記錄資料的版本號和修改者)就知道這個事並不那麼簡單,而且Dynamo對資料衝突這個事是交給使用者自己搞的。就像SVN原始碼衝突一樣,對於同一行程式碼的衝突,只能交給開發者自己來處理。(在本文後後面會討論一下Dynamo的Vector Clock)

Two/Three Phase Commit

這個協議的縮寫又叫2PC,中文叫兩階段提交。在分散式系統中,每個節點雖然可以知曉自己的操作時成功或者失敗,卻無法知道其他節點的操作的成功或失敗。當一個事務跨越多個節點時,為了保持事務的ACID特性,需要引入一個作為協調者的元件來統一掌控所有節點(稱作參與者)的操作結果並最終指示這些節點是否要把操作結果進行真正的提交(比如將更新後的資料寫入磁碟等等)。 兩階段提交的演算法如下:

第一階段:

  • 協調者會問所有的參與者結點,是否可以執行提交操作。
  • 各個參與者開始事務執行的準備工作:如:為資源上鎖,預留資源,寫undo/redo log……
  • 參與者響應協調者,如果事務的準備工作成功,則迴應“可以提交”,否則迴應“拒絕提交”。

第二階段:

  • 如果所有的參與者都回應“可以提交”,那麼,協調者向所有的參與者傳送“正式提交”的命令。參與者完成正式提交,並釋放所有資源,然後迴應“完成”,協調者收集各結點的“完成”迴應後結束這個Global Transaction。
  • 如果有一個參與者迴應“拒絕提交”,那麼,協調者向所有的參與者傳送“回滾操作”,並釋放所有資源,然後迴應“回滾完成”,協調者收集各結點的“回滾”迴應後,取消這個Global Transaction。


可以看到,2PC說白了就是第一階段做Vote,第二階段做決定的一個演算法,也可以看到2PC這個事是強一致性的演算法。在前面討論過Master-Slave的強一致性策略,和2PC有點相似,只不過2PC更為保守一些——先嚐試再提交。 2PC用的是比較多的,在一些系統設計中,會串聯一系列的呼叫,比如:A -> B -> C -> D,每一步都會分配一些資源或改寫一些資料。比如B2C網上購物的下單操作在後臺會有一系列的流程需要做。如果一步一步地做,就會出現這樣的問題,如果某一步做不下去了,那麼前面每一次所分配的資源需要做反向操作把他們都回收掉,所以,操作起來比較複雜。現在很多處理流程(Workflow)都會借鑑2PC這個演算法,使用 try -> confirm的流程來確保整個流程的能夠成功完成。 舉個通俗的例子,西方教堂結婚的時候,都有這樣的橋段:

  1. 牧師分別問新郎和新娘:你是否願意……不管生老病死……
  2. 當新郎和新娘都回答願意後(鎖定一生的資源),牧師就會說:我宣佈你們……(事務提交)

這是多麼經典的一個兩階段提交的事務處理。 另外可以看到其中的一些問題, A)其中一個是同步阻塞操作,這個事情必然會非常大地影響效能。 B)另一個主要的問題是在TimeOut上,比如,

  1. 如果第一階段中,參與者沒有收到詢問請求,或是參與者的迴應沒有到達協調者。那麼,需要協調者做超時處理,一旦超時,可以當作失敗,也可以重試。
  2. 如果第二階段中,正式提交發出後,如果有的參與者沒有收到,或是參與者提交/回滾後的確認資訊沒有返回,一旦參與者的迴應超時,要麼重試,要麼把那個參與者標記為問題結點剔除整個叢集,這樣可以保證服務結點都是資料一致性的。
  3. 糟糕的情況是,第二階段中,如果參與者收不到協調者的commit/fallback指令,參與者將處於“狀態未知”階段,參與者完全不知道要怎麼辦,比如:如果所有的參與者完成第一階段的回覆後(可能全部yes,可能全部no,可能部分yes部分no),如果協調者在這個時候掛掉了。那麼所有的結點完全不知道怎麼辦(問另的參與者都不行)。為了一致性,要麼死等協調者,要麼重發第一階段的yes/no命令。

兩段提交最大的問題就是第3項,如果第一階段完成後,參與者在第二階沒有收到決策,那麼資料結點會進入“不知所措”的狀態,這個狀態會block住整個事務。也就是說,協調者Coordinator對於事務的完成非常重要,Coordinator的可用性是個關鍵。 因些,我們引入三段提交,三段提交在Wikipedia上的描述如下,他把二段提交的第一個段break成了兩段:詢問,然後再鎖資源。最後真正提交。三段提交的示意圖如下:


三段提交的核心理念是:在詢問的時候並不鎖定資源,除非所有人都同意了,才開始鎖資源。

理論上來說,如果第一階段所有的結點返回成功,那麼有理由相信成功提交的概率很大。這樣一來,可以降低參與者Cohorts的狀態未知的概率。也就是說,一旦參與者收到了PreCommit,意味他知道大家其實都同意修改了。這一點很重要。下面來看一下3PC的狀態遷移圖:(注間圖中的虛線,那些F,T是Failuer或Timeout,其中的:狀態含義是 q – Query,a – Abort,w – Wait,p – PreCommit,c – Commit)


其實,三段提交是一個很複雜的事情,實現起來相當難,而且也有一些問題。

看到這裡,我相信你有很多很多的問題,你一定在思考2PC/3PC中各種各樣的失敗場景,你會發現Timeout是個非常難處理的事情,因為網路上的Timeout在很多時候讓你無所事從,你也不知道對方是做了還是沒有做。於是你好好的一個狀態機就因為Timeout成了個擺設。

一個網路服務會有三種狀態:1)Success,2)Failure,3)Timeout,第三個絕對是惡夢,尤其在你需要維護狀態的時候。

Two Generals Problem(兩將軍問題)

Two Generals Problem 兩將軍問題是這麼一個思維性實驗問題: 有兩支軍隊,它們分別有一位將軍領導,現在準備攻擊一座修築了防禦工事的城市。這兩支軍隊都駐紮在那座城市的附近,分佔一座山頭。一道山谷把兩座山分隔開來,並且兩位將軍唯一的通訊方式就是派各自的信使來往于山谷兩邊。不幸的是,這個山谷已經被那座城市的保衛者佔領,並且存在一種可能,那就是任何被派出的信使通過山谷是會被捕。 請注意,雖然兩位將軍已經就攻擊那座城市達成共識,但在他們各自佔領山頭陣地之前,並沒有就進攻時間達成共識。兩位將軍必須讓自己的軍隊同時進攻城市才能取得成功。因此,他們必須互相溝通,以確定一個時間來攻擊,並同意就在那時攻擊。如果只有一個將軍進行攻擊,那麼這將是一個災難性的失敗。 這個思維實驗就包括考慮將軍如何去做這件事情。下面是對於這件事情的思考:

  1. 第一位將軍先發送一段訊息“讓我們在上午9點開始進攻”。然而,一旦信使被派遣,他是否通過了山谷,第一位將軍就不得而知了。任何一點的不確定性都會使得第一位將軍攻擊猶豫,因為如果第二位將軍不能在同一時刻發動攻擊,那座城市的駐軍就會擊退他的軍隊的進攻,導致他的軍對被摧毀。
  2. 知道了這一點,第二位將軍就需要傳送一個確認訊息:“我收到您的資訊,並會在9點的攻擊。”但是,如果帶著確認訊息的信使被抓怎麼辦?所以第二位將軍會猶豫自己的確認訊息是否能到達。
  3. 於是,似乎我們還要讓第一位將軍再發送一條確認訊息——“我收到了你的確認”。然而,如果這位信使被抓怎麼辦呢?
  4. 這樣一來,是不是我們還要第二位將軍傳送一個“確認收到你的確認”的資訊。

於是你會發現,這事情很快就發展成為不管傳送多少個確認訊息,都沒有辦法來保證兩位將軍有足夠的自信自己的信使沒有被敵軍捕獲。


這個問題是無解的。兩個將軍問題和它的無解證明首先由E.A.Akkoyunlu,K.Ekanadham和R.V.Huber於1975年在《一些限制與折衷的網路通訊設計》一文中發表,就在這篇文章的第73頁中一段描述兩個黑幫之間的通訊中被闡明。 1978年,在Jim Gray的《資料庫作業系統注意事項》一書中(從第465頁開始)被命名為兩個將軍悖論。作為兩個將軍問題的定義和無解性的證明的來源,這一參考被廣泛提及。

這個實驗意在闡明:試圖通過建立在一個不可靠的連線上的交流來協調一項行動的隱患和設計上的巨大挑戰。

從工程上來說,一個解決兩個將軍問題的實際方法是使用一個能夠承受通訊通道不可靠性的方案,並不試圖去消除這個不可靠性,但要將不可靠性削減到一個可以接受的程度。比如,第一位將軍排出了100位信使並預計他們都被捕的可能性很小。在這種情況下,不管第二位將軍是否會攻擊或者受到任何訊息,第一位將軍都會進行攻擊。另外,第一位將軍可以傳送一個訊息流,而第二位將軍可以對其中的每一條訊息傳送一個確認訊息,這樣如果每條訊息都被接收到,兩位將軍會感覺更好。然而從證明中來看,他們倆都不能肯定這個攻擊是可以協調的。他們沒有演算法可用(比如,收到4條以上的訊息就攻擊)能夠確保防止僅有一方攻擊。再者,第一位將軍還可以為每條訊息編號,說這是1號,2號……直到n號。這種方法能讓第二位將軍知道通訊通道到底有多可靠,並且返回合適的數量的訊息來確保最後一條訊息被接收到。如果通道是可靠的話,只要一條訊息就行了,其餘的就幫不上什麼忙了。最後一條和第一條訊息丟失的概率是相等的。

 兩將軍問題可以擴充套件成更變態的拜占庭將軍問題 (Byzantine Generals Problem),其故事背景是這樣的:拜占庭位於現在土耳其的伊斯坦布林,是東羅馬帝國的首都。由於當時拜占庭羅馬帝國國土遼闊,為了防禦目的,因此每個軍隊都分隔很遠,將軍與將軍之間只能靠信差傳訊息。 在戰爭的時候,拜占庭軍隊內所有將軍必需達成一致的共識,決定是否有贏的機會才去攻打敵人的陣營。但是,軍隊可能有叛徒和敵軍間諜,這些叛徒將軍們會擾亂或左右決策的過程。這時候,在已知有成員謀反的情況下,其餘忠誠的將軍在不受叛徒的影響下如何達成一致的協議,這就是拜占庭將軍問題。

PAXOS演算法

Wikipedia上的各種Paxos演算法的描述非常詳細,大家可以去圍觀一下。

Paxos 演算法解決的問題是在一個可能發生上述異常的分散式系統中如何就某個值達成一致,保證不論發生以上任何異常,都不會破壞決議的一致性。一個典型的場景是,在一個分散式資料庫系統中,如果各節點的初始狀態一致,每個節點都執行相同的操作序列,那麼他們最後能得到一個一致的狀態。為保證每個節點執行相同的命令序列,需要在每一條指令上執行一個「一致性演算法」以保證每個節點看到的指令一致。一個通用的一致性演算法可以應用在許多場景中,是分散式計算中的重要問題。從20世紀80年代起對於一致性演算法的研究就沒有停止過。

Notes:Paxos演算法是萊斯利·蘭伯特(Leslie Lamport,就是 LaTeX 中的”La”,此人現在在微軟研究院)於1990年提出的一種基於訊息傳遞的一致性演算法。由於演算法難以理解起初並沒有引起人們的重視,使Lamport在八年後1998年重新發表到ACM Transactions on Computer Systems上。即便如此paxos演算法還是沒有得到重視,2001年Lamport 覺得同行無法接受他的幽默感,於是用容易接受的方法重新表述了一遍。可見Lamport對Paxos演算法情有獨鍾。近幾年Paxos演算法的普遍使用也證明它在分散式一致性演算法中的重要地位。2006年Google的三篇論文初現“雲”的端倪,其中的Chubby Lock服務使用Paxos作為Chubby Cell中的一致性演算法,Paxos的人氣從此一路狂飆。(Lamport 本人在他的blog 中描寫了他用9年時間發表這個演算法的前前後後)

注:Amazon的AWS中,所有的雲服務都基於一個ALF(Async Lock Framework)的框架實現的,這個ALF用的就是Paxos演算法。我在Amazon的時候,看內部的分享視訊時,設計者在內部的Principle Talk裡說他參考了ZooKeeper的方法,但他用了另一種比ZooKeeper更易讀的方式實現了這個演算法。

簡單說來,Paxos的目的是讓整個叢集的結點對某個值的變更達成一致。Paxos演算法基本上來說是個民主選舉的演算法——大多數的決定會成個整個叢集的統一決定。任何一個點都可以提出要修改某個資料的提案,是否通過這個提案取決於這個叢集中是否有超過半數的結點同意(所以Paxos演算法需要叢集中的結點是單數)。

這個演算法有兩個階段(假設這個有三個結點:A,B,C):

第一階段:Prepare階段

A把申請修改的請求Prepare Request發給所有的結點A,B,C。注意,Paxos演算法會有一個Sequence Number(你可以認為是一個提案號,這個數不斷遞增,而且是唯一的,也就是說A和B不可能有相同的提案號),這個決議號會和修改請求一同發出,任何結點在“Prepare階段”時都會拒絕其實小於當前提案號的請求。所以,結點A在向所有結點申請修改請求的時候,需要帶一個提案號,越新的提案,這個提案號就越是是最大的。

如果接收結點收到的提案號n大於其它結點發過來的提案號,這個結點會迴應Yes(本結點上最新的被批准提案號),並保證不接收其它<n的提案。這樣一來,結點上在Prepare階段裡總是會對最新的提案做承諾。

優化:在上述 prepare 過程中,如果任何一個結點發現存在一個更高編號的提案,則需要通知 提案人,提醒其中斷這次提案。

第二階段:Accept階段

如果提案者A收到了超過半數的結點返回的Yes,然後他就會向所有的結果釋出Accept Request(同樣,需要帶上提案號n),如果沒有超過半數的話,那就返回失敗。

當結點們收到了Accept Request後,如果對於接收的結果來說,n是最大的了,那麼,它就會修改這個值,如果發現自己有一個更大的提案號,那麼,結點就會拒絕修改。

我們可以看以,這似乎就是一個“兩段提交”的優化。其實,2PC/3PC都是分散式一致性演算法的殘次版本,Google Chubby的作者Mike Burrows說過這個世界上只有一種一致性演算法,那就是Paxos,其它的演算法都是殘次品。

我們還可以看到:對於同一個值的在不同結點的修改提案就算是在接收方被亂序收到也是沒有問題的。

關於一些例項,你可以看一下Wikipedia中文中的“Paxos樣例”一節,我在這裡就不再多說了。對於Paxos演算法中的一些異常示例,大家可以自己推導一下。你會發現基本上來說只要保證有半數以上的結點存活,就沒有什麼問題。

多說一下,自從Lamport在1998年發表Paxos演算法後,對Paxos的各種改進工作就從未停止,其中動作最大的莫過於2005年發表的Fast Paxos。無論何種改進,其重點依然是在訊息延遲與效能、吞吐量之間作出各種權衡。為了容易地從概念上區分二者,稱前者Classic Paxos,改進後的後者為Fast Paxos。

總結

下圖來自:Google App Engine的co-founder Ryan Barrett在2009年的google i/o上的演講:


前面,我們說過,要想讓資料有高可用性,就需要冗餘資料寫多份。寫多份的問題會帶來一致性的問題,而一致性的問題又會帶來效能問題。從上圖我們可以看到,我們基本上來說不可以讓所有的項都綠起來,這就是著名的CAP理論:一致性,可用性,分割槽容忍性,你可以要其中的兩個。

NWR模型

最後我還想提一下Amazon Dynamo的NWR模型。這個NWR模型把CAP的選擇權交給了使用者,讓使用者自己的選擇你的CAP中的哪兩個。

所謂NWR模型。N代表N個備份,W代表要寫入至少W份才認為成功,R表示至少讀取R個備份。配置的時候要求W+R > N。 因為W+R > N, 所以 R > N-W 這個是什麼意思呢?就是讀取的份數一定要比總備份數減去確保寫成功的倍數的差值要大。

也就是說,每次讀取,都至少讀取到一個最新的版本。從而不會讀到一份舊資料。當我們需要高可寫的環境的時候,我們可以配置W = 1 如果N=3 那麼R = 3。 這個時候只要寫任何節點成功就認為成功,但是讀的時候必須從所有的節點都讀出資料。如果我們要求讀的高效率,我們可以配置 W=N R=1。這個時候任何一個節點讀成功就認為成功,但是寫的時候必須寫所有三個節點成功才認為成功。

NWR模型的一些設定會造成髒資料的問題,因為這很明顯不是像Paxos一樣是一個強一致的東西,所以,可能每次的讀寫操作都不在同一個結點上,於是會出現一些結點上的資料並不是最新版本,但卻進行了最新的操作。

所以,Amazon Dynamo引了資料版本的設計。也就是說,如果你讀出來資料的版本是v1,當你計算完成後要回填資料後,卻發現數據的版本號已經被人更新成了v2,那麼伺服器就會拒絕你。版本這個事就像“樂觀鎖”一樣。

但是,對於分散式和NWR模型來說,版本也會有惡夢的時候——就是版本衝的問題,比如:我們設定了N=3 W=1,如果A結點上接受了一個值,版本由v1 -> v2,但還沒有來得及同步到結點B上(非同步的,應該W=1,寫一份就算成功),B結點上還是v1版本,此時,B結點接到寫請求,按道理來說,他需要拒絕掉,但是他一方面並不知道別的結點已經被更新到v2,另一方面他也無法拒絕,因為W=1,所以寫一分就成功了。於是,出現了嚴重的版本衝突。

Amazon的Dynamo把版本衝突這個問題巧妙地迴避掉了——版本衝這個事交給使用者自己來處理。

於是,Dynamo引入了Vector Clock(向量鍾?!)這個設計。這個設計讓每個結點各自記錄自己的版本資訊,也就是說,對於同一個資料,需要記錄兩個事:1)誰更新的我,2)我的版本號是什麼。

下面,我們來看一個操作序列:

  1. 一個寫請求,第一次被節點A處理了。節點A會增加一個版本資訊(A,1)。我們把這個時候的資料記做D1(A,1)。 然後另外一個對同樣key的請求還是被A處理了於是有D2(A,2)。這個時候,D2是可以覆蓋D1的,不會有衝突產生。
  2. 現在我們假設D2傳播到了所有節點(B和C),B和C收到的資料不是從客戶產生的,而是別人複製給他們的,所以他們不產生新的版本資訊,所以現在B和C所持有的資料還是D2(A,2)。於是A,B,C上的資料及其版本號都是一樣的。
  3. 如果我們有一個新的寫請求到了B結點上,於是B結點生成資料D3(A,2; B,1),意思是:資料D全域性版本號為3,A升了兩新,B升了一次。這不就是所謂的程式碼版本的log麼?如果D3沒有傳播到C的時候又一個請求被C處理了,於是,以C結點上的資料是D4(A,2; C,1)。
  4. 如果D3沒有傳播到C的時候又一個請求被C處理了,於是,以C結點上的資料是D4(A,2; C,1)。
  5. 好,最精彩的事情來了:如果這個時候來了一個讀請求,我們要記得,我們的W=1 那麼R=N=3,所以R會從所有三個節點上讀,此時,他會讀到三個版本:
  • A結點:D2(A,2)
  • B結點:D3(A,2; B,1);C結點:D4(A,2; C,1)
  • C結點:D4(A,2; C,1)

6.這個時候可以判斷出,D2已經是舊版本(已經包含在D3/D4中),可以捨棄。

7.但是D3和D4是明顯的版本衝突。於是,交給呼叫方自己去做版本衝突處理。就像原始碼版本管理一樣。

很明顯,上述的Dynamo的配置用的是CAP裡的A和P。

原文地址:http://www.csdn.net/article/2014-01-20/2818197-distributed-system/1

相關推薦

深入解析分散式系統事務處理經典問題模型(轉載分享)

編者按:資料服務的高可用是所有企業都想擁有的,但是要想讓資料有高可用性,就需要冗餘資料寫多份。寫多份的問題會帶來一致性的問題,而一致性的問題又會帶來效能問題,這就會陷入一個無解的死迴圈!這裡所謂資料一致性,就是當多個使用者試圖同時訪問一個數據庫時,如果它們的事務同時使用相同的資料,可能會發生以下四種情況:

架構文摘分散式系統Session一致性問題解析

一、問題的提出 1. 什麼是Session? 使用者使用網站的服務,需要使用瀏覽器與Web伺服器進行多次互動。HTTP協議本身是無狀態的,需要基於HTTP協議支援會話狀態(Session State)的機制。具體的實現方式是:在會話開始時,分配一個 唯

python爬蟲進階(八)分散式系統的高可用與高併發處理

一、應對高併發的基本思路 1、加快單機的速度,例如使用Redis,提高資料訪問頻率;增加CPU的核心數,增大記憶體; 2、增加伺服器的數量,利用叢集。 二、分散式系統的設計 1、無狀態 應用本身沒有狀態,狀態全部通過配置檔案或者叢集的服務端提供並與之同步。比如不同

Spring 事務配置實戰(一)過濾無需事務處理的查詢之類操作

log pla ssi pan spl tail gif aop img <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes

分散式學習筆記三分散式系統session一致性的問題

session的概念 什麼是session? 伺服器為每個使用者建立一個會話,儲存使用者的相關資訊,以便多次請求能夠定位到同一個上下文。這樣,當用戶在應用程式的 Web 頁之間跳轉時,儲存在 Session 物件中的變數將不會丟失,而是在整個使用者會話中一直存在下去。當用戶請求來自應用程式的

訊息中介軟體(一)分散式系統事務一致性解決方案大對比,誰最好使?(轉)

原文轉載至:https://blog.csdn.net/lovesomnus/article/details/51785108   在分散式系統中,同時滿足“一致性”、“可用性”和“分割槽容錯性”三者是不可能的。分散式系統的事務一致性是一個技術難題,各種解決方案孰優孰劣? 在OLTP系統領域,

分散式補償事務處理方案 / 分散式計算是如何控制事務的?

事務原子性,一致性,永續性,隔離性是基本的屬性,這裡不解釋,本篇文章只對分佈性事務方案做說明方案 問題來源 隨著分散式微服務應用盛行,帶來的優勢是顯而易見的,但是在面臨事務的時候,卻變的異常麻煩,因為是在不同的應用內,所以無法在單個應用內做回滾處理,這個時候,就需要有一個單獨的

分散式系統處理引數配置的 4 種方案

一個系統中包含有各種各樣的配置資訊,如一個日誌檔案需要配置以下幾個資訊。 日誌檔案生成主目錄 日誌檔名稱,不同的日誌級別對應不同的檔案 當前日誌級別 還有其他各種業務引數、系統引數等,大多單一系統是直接把這些配置寫死在配置檔案中,當部署到測試、生產環境就再修

深入解析一主多備DG環境,failover的實現過程詳解 以及 11g 容災庫可以線上新增tempfile.

https://yq.aliyun.com/articles/229600   核心,就是11g通過datafille_scn 號來追日誌,而不是日誌序列號來追日誌。   摘要: 在DG中,switchover和failover是兩個重要的概念,也是DG實現的核心。根據不

區塊鏈共識機制分散式系統的Paxos協議

前言:第一次接觸paxos可能很多人不理解這玩意兒有啥用,近幾天一直在研究paxos,不敢說理解的多到位,但是把自己理解的記錄下來,供大家參考。文章主要參考知行學社的《分散式系統與Paxos演算法視訊課程》和知乎話題https://zhuanlan.zhihu.com/p/29706905,希望能對

轉載分散式系統的思考

在討論常見架構前,先簡單瞭解下CAP理論: CAP 是 Consistency、Availablity 和 Partition-tolerance 的縮寫。分別是指: 一致性(Consistency):每次讀操作都能保證返回的是最新資料; 可用性(Availablity):任何一個沒有發生

系統架構設計師分散式系統(中介軟體技術)

        網際網路使得聯機的所有裝置和軟體成為全球共享的浩瀚資源,計算機環境也從集中式發展到分散式。開放式系統的發展使得使用者能夠透明地應用由不同廠商製造的不同機型、不同平臺所組成的異構型計算資源,因此,分散式處理和應用整合自然而然地成為人們的共同需求。      

顛覆大資料分析之Shark分散式系統上的SQL介面

顛覆大資料分析之Shark:分散式系統上的SQL介面 譯者:黃經業    購書 記憶體計算已經成為了海量資料分析的一個重要正規化。這一點可以從兩個方面來進行理解。一方面,儘管當要查詢的資料達到了PB級,但是由於時間和空間的侷限性,在一個叢集環境上僅需64GB的快取就能夠滿足絕大多數的查詢(95

深入解析由SQL解析失敗看開發與DBA的效能之爭

編者注:在很多生產系統中,程式設計師經意不經意寫下的一條SQL都可能帶來效能上的巨大隱患,正確的、不正確的。而DBA就要不斷在這些問題中出生入死,本案例描述的那些不正確的SQL可能給我們帶來的麻煩,而這類錯誤SQL往往為大家所忽視。這樣的問題在最近的客戶案例中不斷湧現,在12c中同樣為我們帶來麻煩,

大咖說 | 胡志琳分散式系統概述

對話 | 大咖 本期參與交流的技術大咖是:胡志琳 胡志琳,資深系統研發,清華大學直博,曾系統設計並實現某重點軍工專案的關鍵裝置,曾就職於滴滴出行等知名網際網路公司。 熱衷於區塊鏈系統的理論研究和工程實現,熟練掌握Bitcoin、Ethereum和EOS等區塊鏈技術。 主要負責分散式系

訊息中介軟體(一)分散式系統事務一致性解決方案大對比,誰最好使?

在分散式系統中,同時滿足“一致性”、“可用性”和“分割槽容錯性”三者是不可能的。分散式系統的事務一致性是一個技術難題,各種解決方案孰優孰劣? 在OLTP系統領域,我們在很多業務場景下都會面臨事務一致性方面的需求,例如最經典的Bob給Smith轉賬的案例。傳統的企業開發,

快訊Oracle自治事務處理資料庫釋出和19c路線圖

Oracle 舊金山時間8月7日宣佈,其自治事務處理(OLTP)資料庫開始提供服務,這距離去年

深入解析Row Movement 的原理和效能影響與關聯

ROW MOVEMENT特性最初是在8i時引入的,其目的是提高分割槽表的靈活性——允許更新Partition Key。這一特性 預設是關閉,只是在使用到一些特殊功能時會要求開啟。除了之前提到的更新Partition Key,還有2個要求開啟的ROW MOVEMENT的功能就是flushback

分散式系統事務

在分散式系統中,同時滿足“一致性”、“可用性”和“分割槽容錯性”三者是不可能的。分散式系統的事務一致性是一個技術難題,各種解決方案孰優孰劣? 寫在前面 在 OLTP 系統領域,我們在很多業務場景下都會面臨事務一致性方面的需求,例如最經典的 Bob 給

【讀書筆記】人人都是架構師分散式系統架構落地與瓶頸突破

《人人都是架構師:分散式系統架構落地與瓶頸突破》。書主要介紹作者遇到的一些實際場景,提供了處理一些典型場景的思路,書中介紹了許多開源軟體,但程式碼和一些細節比較少。分散式入門書,開拓了視野。 大流量消鋒/限流的常規手段 1. 擴容 使用叢集技術對伺