一文看懂分佈式事務

本地事務

事務 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. 更新短信發送記錄爲已發送

注意:

事務消息

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

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

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

具體實現過程:

提供 MQ 事務 callback

退款 callback 查詢

相關理論

二階段提交

二階段提交是解決分佈式事務問題的重要理論基礎,但也存在着明顯的問題:

爲了解決二階段提交出現的問題,又有了三階段提交(Three-phase 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 模式的優勢是:

缺點:

開源項目

seata

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

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

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

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

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

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

AT 模式

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

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

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

TCC 模式

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

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

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

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

Saga 模式

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

  1. 通過狀態圖來定義服務調用的流程並生成 json 狀態語言定義文件

  2. 狀態圖中一個節點可以是調用一個服務,節點可以配置它的補償節點

  3. 狀態圖 json 由狀態機引擎驅動執行,當出現異常時狀態引擎反向執行已成功節點對應的補償節點將事務回滾 (異常發生時是否進行補償也可由用戶自定義決定)

  4. 可以實現服務編排需求,支持單項選擇、併發、子流程、參數轉換、參數映射、服務執行狀態判斷、異常捕獲等功能

狀態機引擎原理

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/NCk1Bkriu4Y-1l8VQqSaaA