分布式事务基础
這一篇主要介紹分布式事務的基礎知識,一些基礎的算法、定理、簡單應用等。下篇文章介紹互聯網業界的具體實踐方案。
1、CAP定理
CAP定理是由加州大學伯克利分校Eric Brewer教授提出來的,其核心思想是任何基于網絡的數據共享,系統最多只能滿足數據一致性(Consistency)、可用性(Availability)和網絡分區容忍(Partition Tolerance)三個特性中的兩個,三個特性的定義如下:
- 一致性(Consistency) : 等同于所有節點擁有數據的最新版本,對于關系型數據庫,要求更新過的數據能被后續的訪問都能看到
- 可用性(Availability) : 數據具備高可用性
- 分區容錯性(Partition tolerance) : 容忍網絡出現分區,分區之間網絡不可達
具體地講在分布式系統中,在任何數據庫設計中,一個Web應用至多只能同時支持上面的兩個屬性。顯然,任何橫向擴展策略都要依賴于數據分區。因此,設計人員必須在一致性與可用性之間做出選擇。
1.1 CAP的應用實例
-
CA(一致性+可用性)without P(容錯性)
單機的Mysql和Oracle;
分布式集群中不存在這種情況,因為多個節點必定考慮主備同步,也就是網絡。 -
CP(一致性+容錯性)without A(可用性)
分布式的數據庫,如Redis,HBase,Zookeeper
任何時刻對ZooKeeper請求能得到一致的數據結果:當master節點網絡故障,會進行選舉機制,選舉時集群不可用。但是它不能保證每次服務請求的可用性,ZooKeeper可能會丟棄一些請求,消費者程序需要重新請求才能獲得結果。 -
AP(可用性+容錯性)without C(一致性)
12306買票
購買的時候提示你是有票的(但是可能實際已經沒票了),但是過了一會系統提示你下單失敗,余票不足。其實舍棄的只是強一致性。退而求其次保證了最終一致性。
Eureka
各個節點平等;有節點掛掉,會立刻換至其他節點,保證服務可用,只不過查到的信息可能不是最新的。在網絡穩定后,當前實例新的注冊信息會被同步到其他節點中。
一旦網絡問題發生,節點之間可能會失去聯系。為了保證高可用,需要在用戶訪問時可以馬上得到返回,導致全局數據的不一致性。
2、 BASE理論
在分布式系統中,我們往往追求的是可用性,它的重要程序比一致性要高,那么如何實現高可用性呢? 前人已經給我們提出來了另外一個理論,就是BASE理論,它是用來對CAP定理進行進一步擴充的。BASE理論指的是:
- Basically Available(基本可用)
- Soft state(軟狀態)
- Eventually consistent(最終一致性)
BASE理論是對CAP中的一致性和可用性進行一個權衡的結果,理論的核心思想就是:我們無法做到強一致,但每個應用都可以根據自身的業務特點,采用適當的方式來使系統達到最終一致性(Eventual consistency)。
3、 Paxos協議
Paxos協議由Leslie Lamport最早在1990年提出,由于Paxos在云計算領域的廣泛應用Leslie Lamport因此獲得了2013年度圖靈獎。
Paxos協議提出只要系統中2f+1個節點中的f+1個節點可用,那么系統整體就可用并且能保證數據的強一致性,它對于可用性的提升是極大的,仍然假設單節點的可用性是P,那么2f+1個節點中任意組合的f+1以上個節點正常的可用性P(total)=,又假設P=0.99,f=2,P(total)=0.9999901494,可用性將從單節點的2個9提升到了5個9,這意味著系統每年的宕機時間從87.6小時降到0.086小時,這已經可以滿足地球上99.99999999%的應用需求。
Leslie寫的兩篇論文:《The Part-Time Parliament》和《Paxos Made Simple》比較完整的闡述了Paxos的工作流程和證明過程,Paxos協議把每個數據寫請求比喻成一次提案(proposal),每個提案都有一個獨立的編號,提案會轉發到提交者(Proposer)來提交,提案必須經過2f+1個節點中的f+1個節點接受才會生效,2f+1個節點叫做這次提案的投票委員會(Quorum),投票委員會中的節點叫做Acceptor,Paxos協議流程還需要滿足兩個約束條件: a)Acceptor必須接受它收到的第一個提案;b)如果一個提案的v值被大多數Acceptor接受過,那后續的所有被接受的提案中也必須包含v值(v值可以理解為提案的內容,提案由一個或多個v和提案編號組成)。
Paxos協議流程劃分為兩個階段,第一階段是Proposer學習提案最新狀態的準備階段;第二階段是根據學習到的狀態組成正確提案提交的階段,完整的協議過程如下:
階段 1
Proposer選擇一個提案編號n ,然后向半數以上的Acceptors發送編號為 n 的prepare請求。
如果一個Acceptor收到一個編號為n 的prepare請求,且 n 大于它已經響應的所有prepare請求的編號,那么它就會保證不會再通過(accept)任何編號小于 n 的提案,同時將它已經通過的最大編號的提案(如果存在的話)作為響應。
階段 2
如果Proposer收到來自半數以上的Acceptor對于它的prepare請求(編號為n )的響應,那么它就會發送一個針對編號為 n ,value值為 v 的提案的accept請求給Acceptors,在這里 v 是收到的響應中編號最大的提案的值,如果響應中不包含提案,那么它就是任意值。
如果Acceptor收到一個針對編號n 的提案的accept請求,只要它還未對編號大于 n 的prepare請求作出響應,它就可以通過這個提案。
用時序圖來描述Paxos協議如圖3所示:
上述Paxos協議流程看起來比較復雜,是因為要保證很多邊界條件下的協議完備性,譬如初試值為空、兩個Proposer同時提交提案等情況,但Paxos協議的核心可以簡單描述為:Proposer先從大多數Acceptor那里學習提案的最新內容,然后根據學習到的編號最大的提案內容組成新的提案提交,如果提案獲得大多數Acceptor的投票通過就意味著提案被通過。由于學習提案和通過提案的Acceptor集合都超過了半數,所以一定能學到最新通過的提案值,兩次提案通過的Acceptor集合中也一定存在一個公共的Acceptor,在滿足約束條件b時這個公共的Acceptor時保證了數據的一致性,于是Paxos協議又被稱為多數派協議。
Paxos協議的真正偉大之處在于它的簡潔性,Paxos協議流程中任何消息都是可以丟失的,一致性保證并不依賴某個特殊消息傳遞的成功,這極大的簡化了分布式系統的設計,極其匹配分布式環境下網絡可能分區的特點,相比較在Paxos協議之前的“兩階段提交(2PC)”也能保證數據強一致性,但復雜度相當高且依賴單個協調者的可用性。
那既然Paxos如此強大,那為什么還會出現ZAB協議?
4、 ZAB 協議
Paxos協議雖然是完備的,但要把它應用到實際的分布式系統中還有些問題要解決:
-
在多個Proposer的場景下,Paxos不保證先提交的提案先被接受,實際應用中要保證多提案被接受的先后順序怎么辦?
-
Paxos允許多個Proposer提交提案,那有可能出現活鎖問題,出現場景是這樣的:提案n在第二階段還沒有完成時,新的提案n+1的第一階段prepare請求到達Acceptor,按協議規定Acceptor將響應新提案的prepare請求并保證不會接受小于n+1的任何請求,這可能導致提案n將不會被通過,同樣在n+1提案未完成第二階段時,假如提案n的提交者又提交了n+2提案,這可能導致n+1提案也無法通過。
-
Paxos協議規定提案的值v只要被大多數Acceptor接受過,后續的所有提案不能修改值v,那現實情況下我還要修改v值怎么辦?
ZooKeeper的核心算法ZAB通過一個簡單的約束解決了前2個問題:所有提案都轉發到唯一的Leader(通過Leader選舉算法從Acceptor中選出來的)來提交,由Leader來保證多個提案之間的先后順序,同時也避免了多Proposer引發的活鎖問題。
ZAB協議的過程用時序圖描述如圖4所示,相比Paxos協議省略了Prepare階段,因為Leader本身就有提案的最新狀態,不需要有提案內容學習的過程,圖中的Follower對應Paxos協議中的Acceptor,Observer對應Paxos中的Learner。
ZAB引入Leader后也會帶來一個新問題: Leader宕機了怎么辦?其解決方案是選舉出一個新的Leader,選舉Leader的過程也是一個Paxos提案決議過程,這里不展開討論。
那如何做到提案的值v可以修改呢?這不是ZAB協議的范疇,研究ZooKeeper源碼后發現它是這么做的:ZooKeeper提供了一個znode的概念,znode可以被修改,ZooKeeper對每個znode都記錄了一個自增且連續的版本號,對znode的任何修改操作(create/set/setAcl)都會促發一次Paxos多數派投票過程,投票通過后znode版本號加1,這相當于用znode不同版本的多次Paxos協議來破除單次Paxos協議無法修改提案值的限制。
從保證一致性的算法核心角度看ZAB確實是借鑒了Paxos的多數派思想,但它提供的全局時序保證以及ZooKeeper提供給用戶可修改的znode才讓Paxos在開源界大放異彩,所以ZAB的價值不僅僅是提供了Paxos算法的優化實現,也難怪ZAB的作者一直強調ZAB和Paxos是不一樣的算法。
CAP理論告訴我們在分布式環境下網絡分區無法避免,需要去權衡選擇數據的一致性和可用性,Paxos協議提出了一種極其簡單的算法在保障數據一致性時最大限度的優化了可用性,ZooKeeper的ZAB協議把Paxos更加簡化,并提供全局時序保證,使得Paxos能夠廣泛應用到工業場景。
5、兩階段提交協議(2PC)
兩階段提交協議(Two-phase Commit Protocol,簡稱 2PC),是分布式事務的核心協議。在此協議中,一個事務管理器(Transaction Manager,簡稱 TM)協調 1 個或多個資源管理器(Resource Manager,簡稱 RM)的活動,所有資源管理器向事務管理器匯報自身活動狀態,由事務管理器根據各資源管理器匯報的狀態(完成準備或準備失敗)來決定各資源管理器是“提交”事務還是進行“回滾”操作。
二階段提交的具體流程如下:
1. 如果所有資源管理器均完成準備(如圖 1),則事務管理器會通知所有資源管理器執行事務提交;
2. 如果任一資源管理器準備失敗(如圖 2 中的資源管理器 B),則事務管理器會通知所有資源管理器進行事務回滾。
6、TCC模型
Try-Confirm-Cancel(TCC)是初步操作(Try)、確認操作(Confirm)和取消操作(Cancel)三種操作的縮寫,這三種操作的業務含義如下:
- Try 階段:對業務系統做檢測及資源預留;
- Confirm 階段:對業務系統做確認提交。默認 Confirm 階段是不會出錯的,只要 Try 成功,Confirm 一定成功;
- Cancel 階段:當業務執行出現錯誤,需要回滾的狀態下,執行業務取消,釋放預留資源。
TCC 是二階段提交協議(Two-phase Commit Protocol,簡稱 2PC)的擴展,Try 操作對應 2PC 中一階段的準備提交事務(Prepare),Confirm 對應 2PC 中二階段事務提交(Commit),Cancel 對應 2PC 中二階段事務回滾(Rollback)。
與 2PC 不同的是,TCC 是一種編程模型,是應用層的 2PC;TCC 的 3 個操作均由編碼實現,通過編碼實現了 2PC 資源管理器的功能。
TCC 自編碼的特性決定 TCC 資源管理器可以跨數據庫、跨應用實現資源管理,將對不同的數據庫訪問、不同的業務操作通過編碼方式轉換一個原子操作,解決了復雜業務場景下的事務問題。同時 TCC 的每一個操作對于數據庫來講都是一個本地數據庫事務,操作結束則本地數據庫事務結束,數據庫的資源也就被釋放;這就規避了數據庫層面的 2PC 對資源占用導致的性能低下問題。
7、柔性事務
7.1 柔性事務的定義
剛性事務(如單數據庫)完全遵循 ACID 規范,即數據庫事務正確執行的四個基本要素:
- 原子性(Atomicity)
- 一致性(Consistency)
- 隔離性(Isolation)
- 持久性(Durability)
柔性事務(如分布式事務)為了滿足可用性、性能與降級服務的需要,降低一致性(Consistency)與隔離性(Isolation)的要求,遵循 BASE 理論:
- 基本業務可用性(Basic Availability)
- 柔性狀態(Soft state)
- 最終一致性(Eventual consistency)
同樣的,柔性事務也部分遵循 ACID 規范:
- 原子性:嚴格遵循
- 一致性:事務完成后的一致性嚴格遵循;事務中的一致性可適當放寬
- 隔離性:并行事務間不可影響;事務中間結果可見性允許安全放寬
- 持久性:嚴格遵循
7.2 柔性事務的分類
柔性事務分為:兩階段型、補償型、異步確保型、最大努力通知型。
-
兩階段型
分布式事務二階段提交,對應技術上的 XA、JTA/JTS,這是分布式環境下事務處理的典型模式。 -
補償型
TCC 型事務(Try-Confirm-Cancel)可以歸為補償型。在 Try 成功的情況下,如果事務要回滾,Cancel 將作為一個補償機制,回滾 Try 操作;TCC 各操作事務本地化,且盡早提交(沒有兩階段約束);當全局事務要求回滾時,通過另一個本地事務實現“補償”行為。
TCC 是將資源層的二階段提交協議轉換到業務層,成為業務模型中的一部分。 -
異步確保型
將一些有同步沖突的事務操作變為異步操作,避免對數據庫事務的爭用,如消息事務機制。 -
最大努力通知型
通過通知服務器(消息通知)進行,允許失敗,有補充機制。
總結
- 上一篇: NetCore + SignalR 实现
- 下一篇: 九城网络集团招聘