一文看懂分布式事務


本地事務

事務Transaction由一組SQL組成,具有四個ACID特性

ACID

Atomicity 原子性 構成事務的一組SQL,要么全部生效,要么全不生效,不會出現部分生效的情況

Consistency 一致性 數據庫經過事務操作后從一種狀態轉變為另一個狀態。可以說原子性是從行為上描述,而一致性是從結果上描述

isolation 隔離性 事務操作的數據對象 相對於 其他事務操作的數據對象相互隔離,互不影響

durability 持久性 事務提交后,其結果就是永久性的,即使發生宕機(非磁盤損壞)

事務實現

對於MySQL數據庫(InnoDB存儲引擎)而言,隔離性是通過不同粒度的鎖機制來實現事務間的隔離;原子性、一致性和持久性通過redo log 重做日志和undo log回滾日志來保證的。

redo log 當數據庫對數據做修改的時候,需要把數據頁從磁盤讀到buffer pool中,然后在buffer pool中進行修改,那么這個時候buffer pool中的數據頁就與磁盤上的數據頁內容不一致,稱buffer pool的數據頁為dirty page 臟數據,如果這個時候發生非正常的DB服務重啟,那么這些數據還沒在內存,並沒有同步到磁盤文件中(注意,同步到磁盤文件是個隨機IO),也就是會發生數據丟失,如果這個時候,能夠在有一個文件,當buffer pool 中的data page變更結束后,把相應修改記錄記錄到這個文件(注意,記錄日志是順序IO),那么當DB服務發生crash的情況,恢復DB的時候,也可以根據這個文件的記錄內容,重新應用到磁盤文件,數據保持一致。

undo log undo日志用於存放數據被修改前的值,如果修改出現異常,可以使用undo日志來實現回滾操作,保證事務的一致性。另外InnoDB MVCC事務特性也是基於undo日志實現的。undo日志分為insert undo log (insert語句產生的日志,事務提交后直接刪除)和 update undo log(delete和update語句產生的日志,由於該undo log可能提供MVVC機制使用,所以不能再事務提交時刪除)。

問題引入

CAP理論

CAP原則又稱CAP定理,指的是在一個分布式系統中,一致性(Consistency)、可用性(Availability)、分區容錯性(Partition tolerance)。CAP 原則指的是,這三個要素最多只能同時實現兩點,不可能三者兼顧。但由於在分布式系統中,分區容錯性必然存在,所以只能在一致性和可用性妥協。

傳統的DBMS,如MySQL其實CA組合,在主從架構下,讀寫分離的情況下,是犧牲一定的一致性的(主從延遲)。

Base理論

base available 基本可用 分布式系統在出現故障時,允許損失部分可用功能,保證核心功能可用

soft state 軟狀態 允許系統中存在中間狀態,這個狀態不影響系統可用性

eventually consistent 最終一致性 系統的中間狀態經過短暫的時間后到達一致狀態

如何解決

場景舉例

考慮這樣一種業務場景,系統A調用系統B的退款服務進行退款,系統A更改內部退款狀態,接着調用系統C的短信服務通知用戶。

在這樣的一個場景下,由於網絡不可靠的必然存在,存在A、B、C三個系統之間一致性的問題。

本地表

針對上述場景,設計兩張表 退款記錄表短信發送記錄表 以及 相應的補償Job

具體實現過程:

  1. 新增退款記錄表,狀態為處理中
  2. 調用系統B的退款服務進行退款
  3. 更新退款記錄狀態為對應的狀態(成功/失敗)
  4. 如果退款成功,則新增短信發送記錄,記錄狀態為待發送
  5. 調用系統C的短信服務,發送短信
  6. 更新短信發送記錄為已發送

退款補償Job 查詢退款記錄表中處理中的記錄,調用系統B的退款服務 退款成功處理:

  1. 新增短信發送記錄,記錄狀態為待發送
  2. 調用系統C的短信服務,發送短信
  3. 更新短信發送記錄為已發送

短信通知補償Job 查詢短信發送記錄中待發送的記錄,調用系統C的短信服務

  1. 調用系統C的短信服務,發送短信
  2. 更新短信發送記錄為已發送

注意:

  • 系統B和系統C需要根據調用方傳的uuid支持冪等
  • 系統A、B、C會出現短暫的不一致,但最終一致

事務消息

可以將其視為兩階段提交消息實現,以確保分布式系統中的最終一致性。事務性消息可確保本地事務的執行和消息的發送可以原子方式執行。

但是由於事務消息異步的特性,調用方拿不到消費方的處理結果,適用於不關心對方的返回結果/對方負責保證處理成功

針對上述場景,增加兩個事務消息的方式解決一致性問題,系統A通過發送事務消息的方式與系統B和系統C進行交互

具體實現過程:

發送退款的事務消息 新增退款記錄,狀態:處理中 Commit退款事務消息

提供MQ事務callback 退款callback查詢

  • 有退款記錄且未處理中則Commit
  • 其他則Rollback

發送短信callback查詢

  • 有退款記錄且成功則Commit
  • 其他則Rollback

退款同步Job 查詢退款記錄表中處理中的記錄,調用系統B的退款查詢接口 同步狀態 退款成功處理:

  • 發送退款的事務消息
  • 更新退款記錄狀態
  • Commit短信事務消息

相關理論

二階段提交

阻塞問題,參與者將協議消息發送給協調器后,它將阻塞直到收到提交或回滾,只能依賴協調者的超時機制

協調者單點問題,如果協調者出現故障,則某些參與者將一直無法收到提交或回滾的消息。

DTP Model

X / Open分布式事務處理DTP(Distributed Transaction Processing)模型是一種軟件體系架構,已經成為事實上的事務模型組件的行為標准。它允許多個應用程序共享由多個資源管理器提供的資源,並允許其工作被協調為全局事務。

ApplicationProgram(AP) 應用程序定義了事務邊界並指定構成事務的操作

ResourceManager(RM) 資源管理器用來管理我們需要訪問的共享資源,我們可以將它理解為關系數據庫、文件存儲系統、消息隊列、打印機等

TransactionManagger(TM) 事務管理器是一個獨立的組件,他為事務分配標識符並監視事務的執行情況,負責事務完成和故障恢復

CommunicationResourceManager(CRM) 通信資源管理器控制一個或多個 TM domain 之間分布式應用的通信。

XA Specification

XA規范是X/Open關於分布式事務處理 (DTP)的規范。規范描述了全局的事務管理器與局部的資源管理器之間的接口。XA規范的目的是允許多個資源(如數據庫,應用服務器,消息隊列,等等)在同一事務中訪問,這樣可以使ACID屬性跨越應用程序而保持有效。XA使用兩階段提交來保證所有資源同時提交或回滾任何特定的事務。

XA規范描述了資源管理器要支持事務性訪問所必需做的事情。

TCC

saga

在 Saga 模式下,分布式事務內有多個參與者,每一個參與者都是一個沖正補償服務,需要用戶根據業務場景實現其正向操作和逆向回滾操作。

分布式事務執行過程中,依次執行各參與者的正向操作,如果所有正向操作均執行成功,那么分布式事務提交。如果任何一個正向操作執行失敗,那么分布式事務會去退回去執行前面各參與者的逆向回滾操作,回滾已提交的參與者,使分布式事務回到初始狀態。

Saga 模式下分布式事務通常是由事件驅動的,各個參與者之間是異步執行的,Saga 模式是一種長事務解決方案。

Saga模式的優勢是:

  • 一階段提交本地數據庫事務,無鎖,高性能;
  • 參與者可以采用事務驅動異步執行,高吞吐;
  • 補償服務即正向服務的“反向”,易於理解,易於實現;

缺點:

  • Saga 模式由於一階段已經提交本地數據庫事務,且沒有進行“預留”動作,所以不能保證隔離性。

開源項目

seata

Seata 是一款開源的分布式事務解決方案,致力於在微服務架構下提供高性能和簡單易用的分布式事務服務。支持AT、TCC、SAGA、XA四種模式,對微服務框架支持友好。

如下圖所示,Seata 中有三大模塊,分別是 TM、RM 和 TC。 其中 TM 和 RM 是作為 Seata 的客戶端與業務系統集成在一起,TC 作為 Seata 的服務端獨立部署。

TC - 事務協調者 維護全局和分支事務的狀態,驅動全局事務提交或回滾。

TM - 事務管理器 定義全局事務的范圍:開始全局事務、提交或回滾全局事務。

RM - 資源管理器 管理分支事務處理的資源,與TC交談以注冊分支事務和報告分支事務的狀態,並驅動分支事務提交或回滾。

在 Seata 中,分布式事務的執行流程:

  • TM 開啟分布式事務(TM 向 TC 注冊全局事務記錄);
  • 按業務場景,編排數據庫、服務等事務內資源(RM 向 TC 匯報資源准備狀態 );
  • TM 結束分布式事務,事務一階段結束(TM 通知 TC 提交/回滾分布式事務);
  • TC 匯總事務信息,決定分布式事務是提交還是回滾;
  • TC 通知所有 RM 提交/回滾 資源,事務二階段結束;

AT模式

AT 模式是一種無侵入的分布式事務解決方案。在 AT 模式下,用戶只需關注自己的“業務 SQL”,用戶的 “業務 SQL” 作為一階段,Seata 框架會自動生成事務的二階段提交和回滾操作。

一階段:業務數據和回滾日志記錄在同一個本地事務中提交,釋放本地鎖和連接資源。 二階段:提交異步化,非常快速地完成。回滾通過一階段的回滾日志進行反向補償。

在一階段,Seata 會攔截“業務 SQL”,首先解析 SQL 語義,找到“業務 SQL”要更新的業務數據,在業務數據被更新前,將其保存成“before image”,然后執行“業務 SQL”更新業務數據,在業務數據更新之后,再將其保存成“after image”,最后生成行鎖。以上操作全部在一個數據庫事務內完成,這樣保證了一階段操作的原子性。

TCC模式

一個分布式的全局事務,整體是 兩階段提交 的模型。全局事務是由若干分支事務組成的,分支事務要滿足 兩階段提交 的模型要求,即需要每個分支事務都具備自己的:

一階段 prepare 行為 二階段 commit 或 rollback 行為

TCC 模式,不依賴於底層數據資源的事務支持:

一階段 prepare 行為:調用 自定義 的 prepare 邏輯。 二階段 commit 行為:調用 自定義 的 commit 邏輯。 二階段 rollback 行為:調用 自定義 的 rollback 邏輯。

所謂 TCC 模式,是指支持把 自定義 的分支事務納入到全局事務的管理中。

Saga模式

目前SEATA提供的Saga模式是基於狀態機引擎來實現的,機制是:

  1. 通過狀態圖來定義服務調用的流程並生成 json 狀態語言定義文件
  2. 狀態圖中一個節點可以是調用一個服務,節點可以配置它的補償節點
  3. 狀態圖 json 由狀態機引擎驅動執行,當出現異常時狀態引擎反向執行已成功節點對應的補償節點將事務回滾 (異常發生時是否進行補償也可由用戶自定義決定)
  4. 可以實現服務編排需求,支持單項選擇、並發、子流程、參數轉換、參數映射、服務執行狀態判斷、異常捕獲等功能

狀態機引擎原理

  • 圖中的狀態圖是先執行stateA, 再執行stateB,然后執行stateC
  • "狀態"的執行是基於事件驅動的模型,stateA執行完成后,會產生路由消息放入EventQueue,事件消費端從EventQueue取出消息,執行stateB
  • 在整個狀態機啟動時會調用Seata Server開啟分布式事務,並生產xid, 然后記錄"狀態機實例"啟動事件到本地數據庫
  • 當執行到一個"狀態"時會調用Seata Server注冊分支事務,並生產branchId, 然后記錄"狀態實例"開始執行事件到本地數據庫
  • 當一個"狀態"執行完成后會記錄"狀態實例"執行結束事件到本地數據庫, 然后調用Seata Server上報分支事務的狀態
  • 當整個狀態機執行完成, 會記錄"狀態機實例"執行完成事件到本地數據庫, 然后調用Seata Server提交或回滾分布式事務

作者:VectorJin
鏈接:https://juejin.im/post/5e066c9ff265da33b0718f89


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM