天天看點

分布式事務與2PC、3PC理論詳解

事務概念

大部分情況下我們所說的事務都是資料庫事務(Database Transaction),後來延時到了非關系型資料庫等其他領域,事務是運作在我們資料庫上的一個邏輯工作單元,運作在工作單元中的所有sql都具有原子性的操作特點。

資料庫事務要滿足ACID(更詳細檢視相關文章):

A:Atomic,原子性,事務必須是原子的工作單元,一個事務裡面的所有操作要麼全部成功,要麼全部失敗。

C:Consistency:一緻性,事務完成時,保證所有資料的狀态是一緻性的。比如轉賬業務,有五個賬戶之間互相轉賬,無論轉賬多少次,怎麼轉賬,五個賬戶的總餘額都必須是不變的。

I:Isolation:隔離性,并發事務對同一資源所做的修改,事務之間所做的修改時隔離的,通過鎖等手段實作。

D:Duration:持久性,事務完成之後,對系統的影響是永久性的,直到另一個事務執行改變其狀态。

隔離性是通過鎖實作的。

原子性、一緻性、持久性是通過一些記錄,比如事務日志、IO等實作。事務日志redo表示事務修改之後的狀态記錄,undo事務日志表示事務修改之前的狀态記錄,事務送出使用redo,事務復原使用undo。

分布式事務

當你的系統是單機系統,并且使用單一資料庫時,利用傳統關系型資料庫的事務特性來實作事務控制非常簡單。但是,當你進行資料庫分庫分表、系統SOA話之後,傳統關系型資料庫的事務特性就不能滿足事務需求了。

分布式事務指的是分布式環境下的事務。。。。

分布式事務産生的原因

  1. 資料庫分庫分表

    當系統資料量達到一定規模時,就要對資料庫進行分庫分表,本來一個資料庫就會分為多個資料庫執行個體,拆分以後,一個操作可能就要對多個資料庫執行個體進行事務操作。

    分布式事務與2PC、3PC理論詳解
    應用系統有個操作需要對DB1修改一條資料,并且需要在DB2中新增一條資料,此時這兩個操作要在同一個事務單元中,此時,就産生了一個分布式事務。

應用系統SOA化

原本的單體系統,單資料庫,配合spring的聲明式事務加上資料庫的事務特性可以很容易實作事務控制,但是,當業務量達到一定程度後,需要對系統SOA話。比如原本的一個電商系統,拆分成如下幾個子系統。

分布式事務與2PC、3PC理論詳解

此時一個生成訂單的操作,分為兩步,訂單表新增一條記錄,庫存表某條記錄庫存數減庫存。這個操作應當在同一事務上進行,并且此時兩個操作處于不同系統、不同資料庫中,此時就産生了一個分布式事務。

2PC送出協定與3PC送出協定

2PC和3PC都是強一緻性的協定。

2PC協定

2PC(Two Phase Commit),二階段送出,是計算機網絡,尤其是在資料庫領域内,為了使得基于分布式系統架構下所有節點在進行事務處理過程中能夠保持原子性和一緻性設計的一種算法。目前,絕大部分關系型資料庫都是采用二階段送出協定來完成分布式事務的處理,利用該協定能夠非常友善地完成所有分布式事務參與者的協調,同一決定事務的送出或者復原。進而能夠有效地保證分布式事務的一緻性,是以二階段送出協定被廣泛應用到許多分布式系統中。

二階段送出就是把事務的送出分為兩個階段來執行。

階段一:送出事務請求

  1. 協調者像所有參與者發送事務内容,詢問是否可以開始事務的操作,并等待個參與者的響應。
  2. 各參與者節點執行事務操作,并記錄相應的事務日志Undo、Redo。
  3. 各參與者回報給協調者事務的執行情況,執行成功傳回yes、執行失敗分會no。
分布式事務與2PC、3PC理論詳解

階段二:執行事務送出

協調者會根據參與者階段一的回報決定是送出事務還是復原事務。

  • 假設參與者全部都成功執行事務成功,傳回yes,那麼協調者就會像所有參與者發出Commit請求。
  • 參與者接收到Commit請求後,會正式進行事務的送出,并再事務完成送出後釋放事務占用的資源。
  • 參與者在完成事務送出後,向參與者發送ack确認資訊。
  • 協調者接收到所有參與者回報的ACK消息後,完成事務。
分布式事務與2PC、3PC理論詳解

假設參與者有一個或者一個以上傳回NO。

  • 協調者向所有參與者發送復原事務請求。
  • 參與者接收到復原事務請後,會利用在階段1中記錄的undo事務日志資訊來執行事務的復原操作,并在事務復原完成後釋放事務占用的資源。
  • 參與者在事務復原之後,像協調者傳回ACK确認資訊。
  • 協調者接收到所有ACK之後,完成事務中斷。
    分布式事務與2PC、3PC理論詳解
    在兩個階段中,階段一因為要涉及到記錄事務日志,磁盤IO等耗時操作,是以2PC送出的時間消耗階段一占據着絕大占比,而階段二的操作相比起來就快很多,相當于一個非常短的時間操作。那麼階段二發生錯誤的機率會比階段一小非常多,是以隻要階段一成功了,階段二發生錯誤的機率是非常小的,因為階段二是一個瞬時操作。那麼就可以大大增加分布式事務的成功率。

優點:原理簡單、實作友善。

缺點:同步阻塞、單點問題、腦裂、太過保守。

同步阻塞:

二階段送出最明顯也是最大的一個問題是同步阻塞問題,這會極大限制了分布式系統的性能,在二階段事務的執行過程中,所有參與者的邏輯都處于阻塞狀态,也就是說各個參與者在等待其他參與者響應的過程中,都處于阻塞狀态,占用着資源。在階段1,可能某些節點的事務執行得快,是以向協調接回報得快,某些節點的事務執行得慢,是以向協調接回報得慢,而協調者要接收到所有參與者的回報才會執行階段二操作,此時事務執行得快的參與者即使事務已經執行完了并作出了回報,依然會阻塞等待階段二的來臨。

單點問題:

一旦協調者出現問題,那麼整個二階段事務送出将無法進行,更為嚴重的是如果協調者在階段二中出現問題,比如來不及向參與者發事務送出請求就當機了,那麼所有參與者都會處于事務資源的鎖定當中,而無法完成事務操作。這個也是屬于同步阻塞問題。

資料不一緻:

在階段二時,協調者向參與者發送Commit送出請求時,發生局部網絡異常(協調者與部分參與者無法通信)或者資訊還沒向全部參與者發送(隻發送了部分)就突然當機時,導緻隻有部分參與者收到了Commit請求,收到了Commit請求的參與者進行事務送出,而沒有收到的參與者無法進行事務送出,于是整個分布式系統便出現了資料不一緻性現象。

太過保守:

如果協調者訓示參與者進行事務送出詢問過程中,參與者出現故障而導緻協調者始終無法擷取到是以參與者的響應資訊的話,這時,協調者隻能依靠自身的逾時機制判斷是否需要中斷事務。這樣的政策顯得比較保守,換句話說2階段送出協定沒有設計較為完善的容錯機制。任意一節點的失敗都會導緻整個事務的失敗。

3PC送出協定(Three Phase Commit)

基于2PC送出協定遇到的問題,出現了3PC送出協定。即三階段送出,把二階段送出的階段一“送出事務請求”拆分成兩個階段,形成由CanCommit、PreCommit、doCommit三個階段組成的分布式事務處理協定。

階段一:Can Commit

  • 事務詢問:協調者向所有的參與者發送一個包含事務内容的canCommit請求,試問參與者是否可以執行事務的送出操作,并開始等待各參與者的響應。
  • 各參與者像協調者回報事務詢問響應,參與者在接收到協調者的canCommit請求後,就判斷自身是否可以進行該事務操作(判斷的邏輯實作者自行确定,也許是僅僅判斷參與者自身有沒有當機和與協調者的網絡是否正常,也有可能還要根據事務資源狀态來判斷),經過判斷後,如果認為自身可以執行事務的,就向協調者傳回yes響應。否則傳回No響應。

階段二:Pre Commit

在階段二,協調者會根據參與者在階段一的回報情況來決定是否可以進行事務的Pre Commit操作。包含兩種可能:

  1. 在階段一所有參與者都傳回了Yes回報,表示都可以執行事務操作。就進行事務預送出:
  • 協調者向所有參與者發送事務與送出請求PreCommit,并進入Prepared階段。
  • 參與者接收到PreCommit請求後,會執行事務操作,并記錄事務日志Redo、UnDo資訊。
  • 如果參與者成功執行了事務,就會回報給協調者ACK響應,同時等待最終指令(送出/復原)。
  1. 在階段一中,假設有一個或一個以上的參與者傳回了No資訊,或者在逾時時間内協調者沒有接收到所有參與者的回報。那麼就會中斷事務。
  • 協調者向所有參與者發送中斷請求(abort請求)。
  • 無論是收到來自協調者的abort請求,還是在等待協調者消息時出現逾時時,參與者都會執行中斷事務操作。

階段三:(Do Commit)

該階段進行事務的真正送出。也會有兩種情況出現。

  1. 在階段三,假設協調者在逾時時間内接收到了來自所有參與者的ACK回報,就會進行事務送出。
  • 協調者從預送出狀态轉換到送出狀态,并向所有參與者發送doCommit請求。
  • 參與者接受到doCommit請求後,會正式進行事務的送出操作,并再完成事務送出之後釋放在整個事務期間占用的事務資源。
  • 參與者在完成事務送出之後。向協調者發送ACK消息。
  • 協調者接收到所有參與者的ACK消息之後,完成事務。
  1. 在階段三,假設有一個或者一個以上的參與者沒有傳回給協調者ACK或者協調者在逾時時間内沒有收到來自所有參與者的ACK回報,就進入事務中斷狀态。
  • 發送中斷請求,協調者向所有參與者發送abort請求。
  • 參與者在接收到abort請求後,會利用階段二記錄的Undo事務日志進行復原操作,并再復原之後釋放整個事務執行期間占用的資源。
  • 參與者在完成事務復原操作後,向協調者回報ACK消息。
  • 協調者接收到所有參與者回報的ACK消息後,中斷事務。

注意:

跟2PC有一個明顯不同點是,2PC隻有協調者有逾時機制,參與者是沒有逾時機制的,也就是2PC時在階段二參與者沒有收到協調者的Commit請求會一直阻塞,占用事務資源。

3PC送出,參與者也會有逾時機制,在階段三時,假設協調者當機或者協調者與參與者之間出現網絡問題,最終導緻參與者無法及時接收來自協調的在第三階段的doCommit或者abort請求時,參與者在等待逾時後,會進行事務送出操作。

優點:

3PC解決了2PC的前兩個問題,即阻塞和單點問題。但是還是沒能解決資料一緻性問題。但是進一步減小了資料不一緻的機率。

解決阻塞問題是減少了參與者的阻塞範圍,這個優化點,主要是避免了參與者在長時間無法與協調者節點通訊(協調者挂掉了)的情況下,無法釋放資源的問題,因為參與者自身擁有逾時機制會在逾時後,自動進行本地commit進而進行釋放資源。而這種機制也側面降低了整個事務的阻塞時間和範圍。

解決了單點問題:因為參與者在逾時後會自動進行本地commit進而進行釋放資源。是以當協調者當機或者與參與者之間出現網絡故障時,并且送出事務并釋放資源,假設所有參與者都沒有接收到協調者的階段三的請求時,或者隻接收了doCommit請求時,事務也能保持一緻,因為接收到的參與者會執行送出操作,逾時的參與者也會執行送出操作。

但是3PC也會出現資料一緻性問題:

在階段三:假設階段二時,有一個或者一個以上的參與者回報給協調者ACK回報,或者協調者在逾時時間内沒有收到所有參與者的ACK回報,協調者在階段三就會向參與者發送abort請求,但是由于協調者與部分參與者存在網絡故障或者協調者在發送給了部分參與者abort請求後就當機了,導緻部分參與者由于逾時而送出事務,部分參與者由于接收到了abort請求而復原事務,這就導緻了不一緻問題。

減小了資料不一緻的機率:

在2PC送出協定,在第二階段無論協調者發送Commit請求還是abort請求給參與者,隻要出現由于協調者與部分參與者存在網絡故障或者協調者在發送給了部分參與者abort請求後就當機了的情況,就會導緻資料不一樣。

在3PC送出協定,在第三階段,如果出現由于協調者與部分參與者存在網絡故障或者協調者在發送給了部分參與者abort請求後就當機了的情況的這個情況,當能接收到協調者消息的部分參與者接收到的消息是doCommit消息,資料還是能夠保持一緻的,因為逾時的參與者也是執行送出操作,隻有當協調者發送給部分參與者的消息是abort請求時,才會出現資料不一緻。

以上兩個協定都不能完全解決資料一緻性問題,還得通過一些補償機制來實作事務一緻性。

分布式事務的解決方案

X/OpenDTP事務模型:

X/OpenDTP(X/Open Distributed Transaction Procession Reference Model):是X/Open這個組織定義的一套分布式事務的标準,也就是定義了規範的API接口,由各個廠商進行具體實作。

這個标準提出了使用二階段送出來保證分布式事務的完成性,後來J2EE也遵循了這套規範,設計并實作了java裡的分布式事務程式設計接口規範-JTA。

X/A事務是 X/Open DTP定義的中間件與資料庫之間的接口規範。X/A接口函數由資料庫廠商提供。

X/OpenDTP事務模型的角色:

X/OpenDTP事務模型有三個角色:

AP:Application,也就是我們的應用系統。

RM:Resources Manager,資料總管,也就是我們的資料庫。

TM:Transaction Manager,事務管理器、事務協調者。負責分布式事務的協調。

流程就與2PC送出一樣。AP類比參與者,TM類比協調者。

Java X/OpenDTP事務模型的實作:

  • JOTM(Java Open Transaction Manager):基于javaee JTA規範實作的。
  • Atomikos ,原本是一個商業項目,後來開源了。

這篇就不展開講這兩個了。

繼續閱讀