簡單聊聊分佈式事務
本文的主要內容分爲四個方面:事務概念、分佈式事務問題、解決方案概覽、開源方案 Seata 及 AT 模式。
一、事務概念回顧
事務定義:事務是併發控制的單位,業務定義的一個操作序列,這些操作要麼都執行,要麼都不執行,它是一個不可分割的工作單位。
本地事務:本地事務是指僅操作單一事務資源的、不需要全局事務管理器進行協調的事務,也稱爲數據庫事務或傳統事務。
執行模式:
分佈式事務:
隨着 SOA 架構、微服務的流行,以及業務複雜後進行服務化拆分,數據庫垂直拆分後會有多實例庫的事務需求,會出現對應的分佈式事務。
定義:分佈式事務是指事務的參與者、支持事務的服務器、資源服務器以及事務管理器分別位於不同的分佈式系統的不同節點之上
場景:
1、 跨數據庫實例 2、 跨服務 3、 混合式分佈式事務
二、分佈式事務問題
場景:調用其他的服務,需要判斷返回狀態後在執行後續的邏輯、一個服務操作了多個數據源的場景
問題:單靠業務邏輯判斷或者補償會非常複雜,幾乎無法保證事務的基本語義和基本特性
三、解決方案概覽
1. 二階段提交
2PC,Two-phase commit protocol,即兩階段提交協議。它引入了一個事務協調者角色,來管理各個參與者(就是各數據庫資源)
問題:**a 同步阻塞 :**二階段提交過程中,所有參與事務操作的節點處於同步阻塞狀態,無法進行其他的操作
**b 單點問題:**協調者發生故障,那麼所有的參與者還都處於鎖定事務資源的狀態中,而無法繼續完成事務操作
**c 數據不一致:**如果分佈式節點出現網絡分區,某些參與者未收到命令,出現數據不一致
2. 三階段提交
3PC 把 2PC 的準備階段再次一分爲二,這樣三階段提交就有 CanCommit、PreCommit、DoCommit 三個階段
改進:1 將 prepare 拆分成 cancommit 和 precommit,減少資源浪費 2 引入超時機制。同時在協調者和參與者中都引入超時機制,等待超時後,繼續 commit
問題:仍然無法解決數據一致性問題
3. 其他方案
-
TCC 補償型事務:TCC(Try、Confirm、Cancel)是兩階段提交的一個變種
-
基於消息的分佈式事務
-
j2ee 中的 JTA 參考 XA 兩階段規範,與 XA 兼容
-
華爲的 ServiceComb:https://servicecomb.apache.org/cn/docs/introduction/
-
螞蟻金服 XTS,DTX
-
阿里巴巴 TXC
-
開源方案 Seata:http://seata.io/zh-cn
四、 開源方案 seata
Seata 是一款開源的分佈式事務解決方案,致力於提供高性能和簡單易用的分佈式事務服務。Seata 將爲用戶提供了 AT、TCC、SAGA 和 XA 事務模式,爲用戶打造一站式的分佈式解決方案
AT 模式是一種無侵入的分佈式事務解決方案。在 AT 模式下,用戶只需關注自己的 “業務 SQL”,用戶的 “業務 SQL” 作爲一階段,Seata 框架會自動生成事務的二階段提交和回滾操作。
**關鍵實現代碼
**
在一階段,Seata 會攔截 “業務 SQL”,解析 SQL 語義後找到“業務 SQL” 要更新的數據,在數據被更新前,將其保存成 “before image”,然後執行“業務 SQL” 更新數據,在數據更新之後,再將其保存成“after image”,最後生成行鎖。以上操作全部在一個數據庫事務內完成,這樣保證了一階段操作的原子性。
二階段如果是提交的話,因爲 “業務 SQL” 在一階段已經提交至數據庫, 所以 Seata 框架只需將一階段保存的快照數據和行鎖刪掉,完成數據清理即可
二階段如果是回滾的話,Seata 就需要回滾一階段已經執行的 “業務 SQL”,還原業務數據。回滾方式便是用“before image” 還原業務數據;但在還原前要首先要校驗髒寫,對比 “數據庫當前業務數據” 和 “after image”,如果兩份數據完全一致就說明沒有髒寫,可以還原業務數據,如果不一致就說明有髒寫,出現髒寫就需要轉人工處理
關鍵設計問題,可以自己學習前思考,邊學習邊尋找答案,會事半功倍:
-
全局鎖和 checklock
-
XID 傳遞問題
-
失敗重試,補償等措施
-
異步的設計和處理 , 比如分支的提交使用異步隊列
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/Mcx13fPfAHgWD3kaErH9Pg