1. 程式人生 > 實用技巧 >分散式事務理論

分散式事務理論

分散式事務

事務

事務指的就是一個操作單元,在這個操作單元中的所有操作最終要保持一致的行為,要麼所有操作都成功,要麼所有的操作都被撤銷。簡單地說,事務提供一種“要麼全部成功,要麼全部失敗”機制。

本地事務

本地事物其實可以認為是資料庫提供的事務機制。說到資料庫事務就不得不說,資料庫事務中的四大特性:

  • A:原子性(Atomicity),一個事務中的所有操作,要麼全部完成,要麼全部失敗

  • C:一致性(Consistency),在一個事務執行之前和執行之後資料庫都必須處於一致性狀態

  • I:隔離性(Isolation),在併發環境中,當不同的事務同時操作相同的資料時,事務之間互不影響

  • D:永續性(Durability),指的是隻要事務成功結束,它對資料庫所做的更新就必須永久的儲存下來

資料庫事務在實現時會將一次事務涉及的所有操作全部納入到一個不可分割的執行單元,該執行單元中的所有操作要麼都成功,要麼都失敗,只要其中任一操作執行失敗,都將導致整個事務的回滾

分散式事務

分散式事務指事務的參與者、支援事務的伺服器、資源伺服器以及事務管理器分別位於不同的分散式系統的不同節點之上。
簡單的說,就是一次大的操作由不同的小操作組成,這些小的操作分佈在不同的伺服器上,且屬於不同的應用,分散式事務需要保證這些小操作要麼全部成功,要麼全部失敗。
本質上來說,分散式事務就是為了保證不同資料庫的資料一致性

分散式事務的場景

單系統訪問多個數據庫

多個微服務訪問同一個資料庫

多個微服務訪問多個數據庫

分散式事務解決方案

1.基於可靠訊息的最終一致性方案

基於可靠訊息服務的方案是通過訊息中介軟體保證上、下游應用資料操作的一致性。假設有A和B兩個系統,分別可以處理任務A和任務B。此時存在一個業務流程,需要將任務A和任務B在同一個事務中處理。就可以使用訊息中介軟體來實現這種分散式事務。

第一步:訊息由系統A投遞到中介軟體

  1. 在系統A處理任務A前,首先向訊息中介軟體傳送一條訊息

  2. 訊息中介軟體收到後將該條訊息持久化,但並不投遞。持久化成功後,向A回覆一個確認應答

  3. 系統A收到確認應答後,則可以開始處理任務A

  4. 任務A處理完成後,向訊息中介軟體傳送Commit或者Rollback請求。該請求傳送完成後,對系統A而言,該事務的處理過程就結束了

  5. 如果訊息中介軟體收到Commit,則向B系統投遞訊息;如果收到Rollback,則直接丟棄訊息。但是如果訊息中介軟體收不到Commit和Rollback指令,那麼就要依靠"超時詢問機制"。

超時詢問機制

系統A除了實現正常的業務流程外,還需提供一個事務詢問的介面,供訊息中介軟體呼叫。當訊息中介軟體收到釋出訊息便開始計時,如果到了超時沒收到確認指令,就會主動呼叫系統A提供的事務詢問介面詢問該系統目前的狀態。該介面會返回三種結果,中介軟體根據三種結果做出不同反應:

提交:將該訊息投遞給系統B
回滾:直接將條訊息丟棄
處理中:繼續等待

第二步:訊息由中介軟體投遞到系統B

訊息中介軟體向下遊系統投遞完訊息後便進入阻塞等待狀態,下游系統便立即進行任務的處理,任務處理完成後便向訊息中介軟體返回應答。

  • 如果訊息中介軟體收到確認應答後便認為該事務處理完畢

  • 如果訊息中介軟體在等待確認應答超時之後就會重新投遞,直到下游消費者返回消費成功響應為止。

一般訊息中介軟體可以設定訊息重試的次數和時間間隔,如果最終還是不能成功投遞,則需要手工干預。這裡之所以使用人工干預,而不是使用讓A系統回滾,主要是考慮到整個系統設計的複雜度問題。

基於可靠訊息服務的分散式事務,前半部分使用非同步,注重效能;後半部分使用同步,注重開發成本。

2.本地訊息表(最大努力通知)

最大努力通知也被稱為定期校對,其實是對第二種解決方案的進一步優化。它引入了本地訊息表來記錄錯誤訊息,然後加入失敗訊息的定期校對功能,來進一步保證訊息會被下游系統消費。

第一步:訊息由系統A投遞到中介軟體

  1. 處理業務的同一事務中,向本地訊息表中寫入一條記錄

  2. 準備專門的訊息傳送者不斷地傳送本地訊息表中的訊息到訊息中介軟體,如果傳送失敗則重試

第二步:訊息由中介軟體投遞到系統B

  1. 訊息中介軟體收到訊息後負責將該訊息同步投遞給相應的下游系統,並觸發下游系統的任務執行

  2. 當下遊系統處理成功後,向訊息中介軟體反饋確認應答,訊息中介軟體便可以將該條訊息刪除,從而該事務完成

  3. 對於投遞失敗的訊息,利用重試機制進行重試,對於重試失敗的,寫入錯誤訊息表

  4. 訊息中介軟體需要提供失敗訊息的查詢介面,下游系統會定期查詢失敗訊息,並將其消費

這種方式的優缺點:

  • 優點:一種非常經典的實現,實現了最終一致性。

  • 缺點:訊息表會耦合到業務系統中,如果沒有封裝好的解決方案,會有很多雜活需要處理。

3.TCC事務補償型方案

TCC即為Try Confirm Cancel,它屬於補償型分散式事務。TCC實現分散式事務一共有三個步驟:

  • Try:嘗試待執行的業務:這個過程並未執行業務,只是完成所有業務的一致性檢查,並預留好執行所需的全部資源

  • Confirm:確認執行業務:確認執行業務操作,不做任何業務檢查, 只使用Try階段預留的業務資源。通常情況下,採用TCC則認為 Confifirm階段是不會出錯的。即:只要Try成功,Confifirm一定成功。若Confifirm階段真的出錯了,需引入重試機制或人工處理。

  • Cancel:取消待執行的業務:取消Try階段預留的業務資源。通常情況下,採用TCC則認為Cancel階段也是一定成功的。若Cancel階段真的出錯了,需引入重試機制或人工處理

TCC兩階段提交與XA兩階段提交的區別是:

  • XA是資源層面的分散式事務,強一致性,在兩階段提交的整個過程中,一直會持有資源的鎖。

  • TCC是業務層面的分散式事務,最終一致性,不會一直持有資源的鎖。

TCC事務的優缺點:

  • 優點:把資料庫層的二階段提交上提到了應用層來實現,規避了資料庫層的2PC效能低下問題。

  • 缺點:TCC的Try、Confifirm和Cancel操作功能需業務提供,開發成本高。

4.兩階段提交(2PC)

2PC即兩階段提交協議,是將整個事務流程分為兩個階段,準備階段(Prepare phase)、提交階段(commitphase),2是指兩個階段,P是指準備階段,C是指提交階段

  • 準備階段:事務管理器給每個參與者傳送Prepare訊息,每個資料庫參與者在本地執行事務,並寫本地的Undo/Redo日誌,此時事務沒有提交。(Undo日誌是記錄修改前的資料,用於資料庫回滾,Redo日誌是記錄修改後的資料,用於提交事務後寫入資料檔案)

  • 提交階段:如果事務管理器收到了參與者的執行失敗或者超時訊息時,直接給每個參與者傳送回滾(Rollback)訊息;否則,傳送提交(Commit)訊息;參與者根據事務管理器的指令執行提交或者回滾操作,並釋放事務處理過程中使用的鎖資源。注意:必須在最後階段釋放鎖資源。

第一階段

  • 各參與者都成功的情況

首先事務協調者向所有參與者傳送 prepare 請求。
參與者開始執行各自的資料更新,寫入各自的 Undo Log 和 Redo Log。
參與者執行成功後,暫時不提交事務,向協調者傳送 Done 訊息。
進入第二階段。

第一階段

  • 有參與者失敗的情況

向協調者傳送 Fail 訊息,協調者產生事務中斷
  • 事務中斷
協調者向所有參與者發出 Rollback 請求。
參與者收到 Rollback 請求之後,會利用其在階段一種記錄的 Undo 資訊來執行事務回滾操作,並在完成回滾之後釋放在整個事物執行期間佔用的資源。
參與者在完成事物回滾之後,向協調者傳送 Ack 訊息。
中斷事務

第二階段

所有參與者的都執行成功,則協調者下發 Commit 訊息,參與者提交本地事務,釋放鎖住的資源,並向協調者傳送 Ack 確認。

當協調者受到所有的參與者確認訊息後,整個分散式事務結束

二階段提交的優缺點:

  • 優點:實現方便

  • 缺點:

    同步阻塞:在分散式事務的執行過程中,存在多次通訊,佔用時間長,並且在這個過程中所有節點處於阻塞狀態,每個參與者持有的資源始終要加鎖。
    單點故障:由上面可知協調者扮演著非常重要的角色,一旦協調者發生故障,參與者就會一直阻塞下去。尤其在第二階段,協調者發生故障,那麼所有的參與者還都處於鎖定事務資源的狀態中,而無法繼續完成事務操作。
    資料不一致:在第二階段中,當協調者向參與者傳送 commit 請求之後,發生了局部網路異常或者在傳送 commit 請求過程中協調者發生了故障,就會導致只有一部分參與者接受到了commit 請求。而在這部分參與者接到 commit 請求之後就會執行 commit 操作,但是其他未接到 commit 請求的機器則無法執行事務提交,就導致了資料的不一致。