一文讀懂分佈式事務(最全)

1. 事務基本概念

1.1 什麼是事務?

事務是恢復和併發控制的基本單位,事務有四個特性(ACID),原子性(Atomicity),一 致性(Consistency),隔離性(Isolation),持久性(Durability)。

1.2 事務經典場景

假設這樣一個場景:
A 給 B 轉賬 100,流程步驟如下:
1、A 減 100
2、B 多 100。
如果第一步驟執行後,系統崩潰掉了。會怎麼樣呢?
問題:A 被減掉了 100,但 B 的錢未能加 100. 此時,A + B 的金錢總額憑空少了 100。數據 不一致了。
解決思路呢?我們希望步驟 1 和步驟 2 能夠綁定在一起執行,不可分;並且在步驟 1 和步驟 2執行的過程中,儘量規避中間狀態。即謂事務。 

1.3 事務原理與鎖

1.3.1 鎖的問題場景:

多對一問題,多個操作者同時操作一個資源,而資源的狀態變化是非原子的(有中間態), 哄搶會導致資源狀態混亂

 

 

1.3.2 事務的問題場景:

一對多的問題,一個操作者需要綁定操作一系列資源(比如多條 sql),若任何一條操作失敗,

都會導致整個操作失去意義;

 

 

 

 

 

 

1.3.3 事務的實現:

1. redo log

redo log 叫做重做日誌,是用來實現事務的持久性。
該日誌文件由兩部分組成:重做日誌緩衝(redo log buffer)以及重做日誌文件(redo log),前者是在內存中,後者在磁盤中。當事務提交之後會把所有修改信息都會存到該日誌中。

PS:mysql 爲了提升性能不會把每次的數據修改都實時同步到磁盤,而是會先存到 Boffer Pool(緩衝池)裏頭,把這個當作緩存 來用。然後使用後臺線程去做緩衝池和磁盤之間的同步。

redo log 主要用來恢復數據, 用於保障,已提交事務的持久化特性(宕機時,redo log 的信息是全的)

2.undo log

undo log 叫做回滾日誌,用於記錄數據被修改前的信息。他正好跟前面所說的重做日誌所記錄的相反,重做日誌記錄數據被修改後的信息。
undo log 主要記錄的是數據的邏輯變化,爲了在發生錯誤時回滾之前的操作,需要將之前的操作都記錄下來,然後在發生錯誤 時纔可以回滾。
PS:mysql 每次寫入數據或者修改數據之前都會把修改前的信息記錄到 undo log
undo log 是用來回滾數據,用於保障 未提交事務的原子性

 

3. mysql 鎖技術
當多個請求同時來臨時,mysql 要控制讀讀可並行,而寫讀,寫寫不能並行

4. MVCC 基礎
MVCC (MultiVersion Concurrency Control) 叫做多版本併發控制。
InnoDB 的 MVCC ,是通過在每行記錄的後面保存兩個隱藏的列來實現的。這兩個列,一個保存了行的創建時間,一個保存了 行的過期時間,當然存儲的並不是實際的時間值,而是系統版本號。他的主要實現思想是通過數據多版本來做到讀寫分離。從而實現不加鎖讀進而做到讀寫並行。

事務的原子性是通過 undo log 來實現的
事務的持久性是通過 redo log 來實現的
事務的隔離性是通過 (讀寫鎖+MVCC)來實現的
而事務的終極大 boss 一致性是通過原子性,持久性,隔離性來實現的!!!

 

1.4 事務的操作過程

1.編程式事務:使用 TransactionTemplate 或者直接使用底層的 TransactionManager 來操作事務 commit 或者rollback。
2.聲明式事務:建立在 AOP 基礎上,通過對方法前後進行攔截,加入編程式事務裏的流程控制邏輯。使用的時候只需要在方法前 面加上@Transactional 註解

 

2 分佈式事務

2.1 分佈式事務概念

2.1.1 分佈式事務產生的原因

隨着互聯網高速發展,事務的參與者、支持事務的服務器、資源服務器以及事務管理器分別位於不同的分佈式系統的不同節點 之上。簡單的說,就是一次大的操作由不同的小操作組成,這些小的操作分佈在不同的服務器上,且屬於不同的應用。在這種 環境中,我們之前說過數據庫的 ACID 四大特性,已經無法滿足我們分佈式事務。

 

 

 

 

 

 

2.1.2 CAP 理論

CAP 定理,又被叫作布魯爾定理。
CAP 指的是:一致性(Consistency)、可用性(Availability)、分區容錯性(Partition tolerance)。

CAP 定律說的是,在一個分佈式系統中,最多隻能滿足 C、A、P 中的兩個,不可能三個同時滿足。而在分佈式系統中,網絡無法 100% 可靠,分區其實是一個必然現象。

如果我們選擇了 CA 而放棄了 P,那麼當發生分區現象時,爲了保證一致性,這個時候必須拒絕請求,但是 A 又不允許,所以分佈式系統理論上 不可能選擇 CA 架構,只能選擇 CP 或者 AP 架構。

而且,顯然,任何橫向擴展策略都要依賴於數據分區。因此,設計人員必須在一致性與可用性之間做出選擇。

 

2.1.3 BASE 理論

 Basically Available(基本可用) : 分佈式系統在出現故障時,允許損失部分可用功能,保證核心功能可用

往往在分佈式系統中無法實現完全一致性,於是有了 BASE 理論,它是對 CAP 定律的進一步擴充BASE 指的是:

 

  •   Soft state(軟狀態) : 允許系統中存在中間狀態,這個狀態不影響系統可用性

  •   Eventually consistent(最終一致性) : 經過一段時間後,所有節點數據都將會達到一致

BASE 理論是對 CAP 中的一致性和可用性進行一個權衡的結果
BASE 理論核心思想就是:我們無法做到強一致,但每個應用都可以根據自身的業務特點,採用適當的方式來使系統達到最終一致性

BASE 和 ACID 是相反的,它完全不同於 ACID 的強一致性模型,而是通過犧牲強一致性來獲得可用性,並允許數據在一段時 間內是不一致的,但最終達到一致狀態。

 

 

 

 

 

 

 

2.2 基於 XA 協議的兩階段提交

 

X/Open 組織提出了分佈式事務的規範 ----- XA 協議
XA 協議包含兩部分:事務管理器和本地資源管理器。其中本地資源管理器往往由數據庫實現,目前主流的關係型數據庫都實現了 XA 接口, 而事務管理器作爲全局的調度者,負責各個本地資源的提交和回滾。
XA 的核心,便是全局事務,通過 XA 二階段提交協議,與各分佈式數據交互,分準備與提交兩個階段 邏輯流程如下圖:

 

 

 

 

 

在 XA 協議中事務分爲兩階段:

 

事務管理器要求每個涉及到事務的數據庫預提交(precommit)此操作,並反映是否可以提交。 事務協調器要求每個數據庫提交數據,或者回滾數據。

優點:

儘量保證了數據的強一致,實現成本較低,在各大主流數據庫都有自己實現,對於 MySQL 是從 5.5 開始支持。

缺點:

1、單點問題:事務管理器在整個流程中扮演的角色很關鍵,如果其宕機,比如在第一階段已經完成,在第二階段正準備提交 的時候事務管理器宕機,資源管理器就會一直阻塞,導致數據庫無法使用。、

2、同步阻塞:在準備就緒之後,資源管理器中的資源一直處於阻塞,直到提交完成,釋放資源。

3、數據不一致:兩階段提交協議雖然爲分佈式數據強一致性所設計,但仍然存在數據不一致性的可能。

 

比如在第二階段中,假設協調者發出了事務 Commit 的通知,但是因爲網絡問題該通知僅被一部分參與者所收到並執行 了 Commit 操作,其餘的參與者則因爲沒有收到通知一直處於阻塞狀態,這時候就產生了數據的不一致性。

兩階段提交方案鎖定資源時間長,對性能影響很大,基本不適合解決微服務事務問題。

2.3 3PC事務

3PC,全稱 “three phase commit”,是 2PC 的改進版,其將 2PC 的 “提交事務請求” 過程一分爲二。

 

 

2.3.1第一個階段: CanCommit

1.事務詢問:協調者向所有的參與者發送一個包含事務內容的 canCommit 請求,詢問是否可以執行事務提交操作,並開始等待各參與者的響應。

2.各參與者向協調者反饋事務詢問的響應:參與者接收來自協調者的 canCommit 請求,如果參與者認爲自己可以順利執行事務,就返回 Yes,否則反饋 No 響應。

這一階段主要是確定分佈式事務的參與者是否具備了完成 commit 的條件,並不會執行事務操作。不鎖表

 

2.3.2 第二階段:precommit

協調者在得到所有參與者的響應之後,會根據結果執行 2 種操作:執行事務預提交,或者中斷事務。

1. 執行事務預提交分爲 3 個步驟:

  •   發送預提交請求:協調者向所有參與者節點發出 preCommit 的請求,並進入 prepared 狀態。

  •   事務預提交:參與者受到 preCommit 請求後,會執行事務操作,對應 2PC 中的 “執行事務”,也會 Undo 和Redo 信息記錄到事務日

    志中。

  •   各參與者向協調者反饋事務執行的結果:如果參與者成功執行了事務,就反饋 Ack 響應,同時等待指令:提交(commit) 或終止(abor)。

2. 中斷事務也分爲 2 個步驟:

  •   發送中斷請求:協調者向所有參與者節點發出 abort 請求 。

  •   中斷事務:參與者如果收到 abort 請求或者超時了,都會中斷事務。

 

2.3.3 第三階段:docommit

1. 執行提交

  •   發送提交請求:進入這一階段,如果協調者正常工作,並且接收到了所有協調者的 Ack 響應,那麼協調者將從 “預提交” 狀態變爲 “提 交” 狀態,並向所有的參與者發送 doCommit 請求 。

  •   事務提交:參與者收到 doCommit 請求後,會正式執行事務提交操作,並在完成之後釋放在整個事務執行期間佔用的事務資源。

  •   反饋事務提交結果:參與者完成事務提交後,向協調者發送 Ack 消息。

  •   完成事務:協調者接收到所有參與者反饋的 Ack 消息後,完成事務。

2. 中斷事務 (假設有任何參與者反饋了 no 響應,或者超時了,就中斷事務)。

  •   發送中斷請求:協調者向所有的參與者節點發送 abort 請求。

  •   事務回滾:參與者接收到 abort 請求後,會利用其在二階段記錄的 undo 信息來執行事務回滾操作,並在完成回滾之後釋放整個事務執行

    期間佔用的資源。

  •   反饋事務回滾結果:參與者在完成事務回滾之後,想協調者發送 Ack 消息。

  •   中斷事務:協調者接收到所有的 Ack 消息後,中斷事務。

 

2.3.4 與 2pc 的區別

注意:在階段三,可能會出現 2 種故障:協調者出現問題/協調者和參與者之間的網絡故障一段出現了任一一種情況,最終都會導致參與者無法收到 doCommit 請求或者 abort 請求, 針對這種情況,參與者都會在等待超時之後,繼續進行事務提交。

優點:
相比較 2PC,最大的優點是減少了參與者的阻塞範圍(第一個階段是不阻塞的),
並且能夠在單點故障後繼續達成一致(2PC 在提交階段會出現此問題,而 3PC 會根據協調者的狀態進行回滾或者提交)。
缺點:
如果參與者收到了 preCommit 消息後,出現了網絡分區,那麼參與者等待超時後,都會進行事務的提交,這必然會出現事務不一致的問題

2.4 TCC方案

 

TCC 其實就是採用的補償機制,其核心思想是:針對每個操作,都要註冊一個與其業務邏輯對應的確認和補償(撤銷)操作。其將整個業務邏輯的每個分支顯式的分成了 Try、Confirm、Cancel 三個操作。Try 部分完成業務的準備工作,confirm 部分完成業務的提交,cancel

部分完成事務的回滾。

優點:跟 2PC 比起來,實現以及流程相對簡單了一些,但數據的一致性比 2PC 也要差一些

缺點: TCC 屬於應用層的一種補償方式,所以需要程序員在實現的時候多寫很多補償的代碼,而且補償的時候也有可能失敗,在一些場景中,一些 業務流程可能用 TCC 不太好定義及處理。

 

2.5 MQ(事務消息)
目前,僅阿里雲的 RocketMQ 支持事務消息。幫助用戶實現類似 X/Open XA 的分佈事務功能,通過 MQ 事務消息能達到分佈式事務的最終一致。

 

  • 1、發送方向 MQ 服務端發送消息

  • 2、MQ Server 將消息持久化成功之後,向發送方 ACK 確認消息已經發送成功,此時消息爲半消息

  • 3、發送方開始執行本地事務邏輯

  • 4、發送方根據本地事務執行結果向 MQ Server 提交二次確認(Commit 或是 Rollback),MQ Server 收到 Commit狀態則將半消息標記爲可投遞,訂閱方最終將收到該消息;MQ Server 收到 Rollback 狀態則刪除半消息,訂閱方將不會接受該消息

 

          5、在斷網或者是應用重啓的特殊情況下,上述步驟 4 提交的二次確認最終未到達 MQ Server,經過固定時間後             MQ Server 將對該消息發起消息回查。

  • 6、發送方收到消息回查後,需要檢查對應消息的本地事務執行的最終結果

  • 7、發送方根據檢查得到的本地事務的最終狀態再次提交二次確認,MQ Server 仍按照步驟 4 對半消息進行操作

  • 其中,事務消息發送對應步驟 1、2、3、4,事務消息回查對應步驟 5、6、7

  • 2.6 Lcn事務

  • 2.6.1 背景

  • LCN 名稱是由早期版本的 LCN 框架命名,在設計框架之初的 1.0 ~ 2.0 的版本時框架設計的步驟是如下,各取其首字母得來的 LCN 命名。

  • 鎖定事務單元(lock) 確認事務模塊狀態(confirm)通知事務(notify)

  • 2.6.2 框架定位
    LCN 並不生產事務,LCN 只是本地事務的協調工

  • TX-LCN 定位於一款事務協調性框架,框架其本身並不操作事務,而是基於對事務的協調從而達到事務一致性的效果。

  • 2.6.3 事務控制原理TX-LCN 由兩大模塊組成, TxClient、TxManager,

  • TxClient 作爲模塊的依賴框架,提供 TX-LCN 的標準支持,TxManager 作爲分佈式事務的控制方。事務發起方或者參與反都由TxClient 端來控制。

  • 原理圖:

 

 1.創建事務組
是指在事務發起方開始執行業務代碼之前先調用 TxManager 創建事務組對象,然後拿到事務標示 GroupId 的過程。

 2.加入事務組
添加事務組是指參與方在執行完業務方法以後,將該模塊的事務信息通知給 TxManager 的操作。

 3.通知事務組
是指在發起方執行完業務代碼以後,將發起方執行結果狀態通知給 TxManager,TxManager 將根據事務最終狀態和事務組的信息 來通知相應的參與模塊提交或回滾事務,並返回結果給事務發起方。

2.7 Seata事務

Seata(Simple Extensible Autonomous Transaction Architecture) 是 阿里巴巴開源的分佈式事務中間件,以高效並且對業 務 0 侵入的方式,解決微服務場景下面臨的分佈式事務問題。

2.7.2 設計思想

seata 的 AT 模式,採用的是大量運用在數據庫軟件的 Write Ahead Log 思想,即把事務的信息以事務日誌的方式記錄下來。這種處理方式,實際上是對傳統兩階段提交的一種改進和優化。主要有幾個關鍵點:

  1. 傳統兩階段提交協議是阻塞協議,性能差

  2. 傳統兩階段提交協議高可用性不好

  3. 傳統兩階段提交協議的全局事務隔離機制不支持

  4. 根據八二原則,80% 的涉及到全局事務的業務是能正常完成並提交的。

因此,在 AT 模式下,seata 採取的做法是,一個事務分支的數據庫操作執行完後,馬上進行本地事務的提交,從而釋放相關的數據庫 資源。

 

  • 1、分支事務中數據的本地鎖由本地事務管理,在分支事務 Phase1 結束時釋放。

  • 2、同時,隨着本地事務結束,連接 也得以釋放。

  • 3、分支事務中數據的全局鎖在事務協調器側管理,在決議 Phase2 全局提交時,全局鎖馬上可以釋放。只有在決議全 局回滾的情況下,全局鎖才被持有至分支的 Phase2 結束。

 

 

2.7.3 本地事務執行流程

在進行本地提交的前提是,seata 會解析 SQL,獲取數據庫表的元數據,根絕 SQL 類型,選擇性地生成數據的前置鏡像和後置鏡像, 保存在 undo_log 表中,並且要求與保存 undo_log 與業務 SQL 在同一個本地事務內。

2.7.4 全局事務提交流程

因爲每個分支事務的本地事務都已經被提交,所以如果全局事務能夠順利進行到“提交“這一階段,那麼意味着所有事務分支的本地事 務都已經被提交了,數據的一致性已經得到了保證。

這個時候全局事務的提交就變得十分輕量級,就是把 undo_log 對應的記錄刪掉即可,即使是當時刪除失敗了,也已經不會影響全局事 務的最終結果,這次刪不了,那就待會再刪,程序刪不了,沒事,頂多人工刪。

2.7.5 全局事務回滾流程

如果全局事務的任何一個事務分支失敗了,那麼全局事務就進入“回滾“流程,回滾時依據先前保存好數據鏡像,將原來的數據回放回 去。

如果全局回放成功,那麼數據的一致性也就得到了保證,如果回放不成功,那麼事務就進入異常。應對異常,可能需要重試,可能需要 人工介入。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章