分布式事物的設計與實踐


分布式事物設計與實踐

數據一致性定義

  • 任何人
  • 任何時間
  • 任何地點
  • 任何接入方式
  • 任何服務
  • 數據都是一致的

數據不一致產生的原因

  • 數據分散在多處
    • 多個DB
    • DB和緩存
  • 二手交易平台案例
    • 用戶,交易,商品等功能

分布式事物產生的原因

剛開始是一個單體進程

image.png

經過演變,單體式服務演變成微服務,每個服務都是單獨的進程

image.png

在用戶請求量大的時候,為了緩解數據庫的壓力,添加了分布式緩存

image.png

分布式事物案例

電商平台購買商品

下單->減庫存->支付

image.png

這就是分布式事物問題,當APP要買東西,這個操作會涉及到多個服務,意味着要操作多個數據庫,這樣本地事物就無法保證數據的一致性,所以就產生了分布式事物問題.

分布式事物場景

  • 電商下單場景
    • 下單
    • 發送消息到MQ
  • 一致性保證
    • 本地事物
      • 下單操作
      • 發送MQ消息操作
      • 放進一個本地事物

上述做法有什么問題?

image.png

問題:如果發送消息超時了,你是不知道MQ的返回結果是成功和失敗的,,timeout這操作不是一個原子的

 

分布式事物分類

  • 剛性分布式事物
    • 強一致性
    • XA模型
    • CAP
      • CP
  • 柔性分布式事物
    • 最終一致性
    • CAP,BASE理論
      • AP

剛性分布式事物

滿足傳統事物特性

ACID( Atomicity-原子性, Consistency-一致性,Isolation-隔離性,Durability-持久性)

XA模型

  • XA是X/Open CAE Specification(Distributed Transaction Processing)模型中定義,XA規范由AP,RM,TM組成
  • 其中應用程序(Application Program簡稱AP),AP定義事物邊界(定義事物開始和結束)並訪問邊界事物內的資源
  • 資源管理器(Resource Manager簡稱RM),RM管理計算機共享的資源,資源及數據庫等
  • 事物管理器(Transaction Manager,簡稱TM),負責管理全局事物,分配事物唯一標識,監控事物的執行進度,並負責事物的提交,,回滾,失敗恢復等

image.png

2PC(兩階段提交-XA規范標准實現)

  • 案例
    • 組織爬山
  • 過程
    • 二階段提交,是XA規范的標准實現
    • TM發起prepare投票
    • RM都同意后,TM再發起Commit
    • Commit 過程出現宕機等異常,節點服務重啟后,根據XA recover 再次進行commit補償
  • 缺點
    • 同步阻塞模型
    • 數據庫資源鎖定時間過長
    • 全局鎖(隔離級別-串行化),並發低
    • 不適合長事物場景

image.png

柔性分布式事物

  • CAP
    • 分布式環境下P一定需要,CA權衡折中
  • BASE理論
    • Basically Available-基本可用
    • Soft state 柔性狀態
    • Eventual consistency 最終一致性
  • 架構思考
    • 柔性事物是對XA協議的妥協,他通過降低強一致性要求,從而降低數據庫資源鎖定時間,提升可用性
  • 架構經典實現
    • TCC模型
    • Saga模型

 

TCC模型

  • Try-confirm-cancel
  • TCC模型完全交由業務實現,每個子業務都需要實現Try-Confirm-cancel接口,對業務侵入大
    • 資源鎖定交由業務方
  • try
    • 嘗試執行業務,完成所有檢查,預留必要的業務資源
  • confirm
    • 真正執行業務,不再做業務檢查
  • Cancel
    • 釋放Try階段預留的業務資源
  • 案例
    • 匯款服務,收款服務案例
      • A用戶向B用戶匯款500元
    • 匯款服務
      • try
        • 檢查A賬戶的有效性,及查看A賬戶的狀態是否為"轉賬中"或者"凍結"
        • 檢查A賬戶余額是否充足
        • 從A賬戶中扣減500元,並將狀態設置為轉賬中
        • 預留扣減資源,將從A往B賬戶轉賬500元這個事件存入消息或者日志中
      • confirm
        • 不做任何操作
      • cancel
        • A賬戶增加500元
        • 從日志或者消息中,釋放扣減資源
    • 收款服務
      • try
        • 檢查B賬戶是否有效
      • confirm
        • 讀取日志或消息,B賬戶增加500元
        • 從日志或者消息中,釋放扣減資源
      • cancel
        • 不做任何操作

Saga模型

  • 起源於1987年Hector & Kenneth發表的論文Sagas
  • Saga模型把一個分布式事物拆分為多個本地事物,每個本地事物都有相應的執行模塊和補償模塊(對應TCC中的confirm和cancel)
  • 當Saga事物中任意一個本地事物出錯時,可以通過調用相關的補償方法恢復之前的事物,到達事物最終一致性
  • 當每個Saga子事物T1,T2,....TN都有對應的補償定義C1,C2,....CN-1,那么Saga系統可以保證
    • 子事物序列T1,T2,.....TN得以完成(最佳情況)
    • 或者序列T1,T2,...TJ,CJ-1,..., C2,C1,0<J<N,得以完成
  • Saga隔離性
    • 業務層控制並發
      • 在應用層加鎖
      • 應用層預先凍結資源等
  • Saga恢復方式
    • 向后恢復,補償所有已完成的事物,如果任意子事物的失敗
    • 向前恢復,重試失敗的事物,假設每個子事物最終都會成功

 

剛性分布式事物VS柔性分布式事物

 

剛性事物(XA)

柔性事物

業務改造

回滾

支持

實現補償接口

一致性

強一致(CP)

最終一致性(AP)

隔離性

原生支持

實現資源鎖定接口

並發性能

嚴重衰退

略微衰退

適合場景

短事物,並發較低

長事物,高並發

我們如何實踐

  • 問題通用解決思路
    • 解決這個問題本身
    • 讓問題本身消失
      • 圓珠筆筆芯漏油解決
  • 圓珠筆筆芯在寫2W次就開始漏油,如果要解決這個問題本身,那么就是加入更好的材料,更高端的技術,如果是讓問題本身消失呢,就是固定一個次數,讓它只能寫1.5W次就沒油開始丟棄,這樣的兩種辦法
  • 首選是讓問題本身消失,次選是解決這個問題本身
  • 方案一:從業務場景消除分布式事物
    • 思路:核心業務先處理,其他業務異步處理
  • 方案二:柔性分布式事物

柔性分布式事物實踐

  • 通用處理思路
    • 本地事物-->短事物
    • 分布式事物-->長事物
    • 轉變成多個短事物
    • 案例
      • A[下單]->B[減庫存]->C[支付]
        • A->DB1
        • B->DB2
        • C->DB3
        • A/B/C都成功
        • A/B成功,C失敗
          • 補償
  • 業務場景
    • 異步場景
      • 基於MQ消息驅動分布事物
    • 同步場景
      • 基於異步補償分布

異步場景分布式事物設計

異步場景

商品交易

下單,支付

image.png

方案一:業務方提供本地操作成功回查功能

    • 事物消息:MQ提供類似X/Open XA的分布式事物功能,通過MQ事物消息能達到分布式事物的最終一致
    • 半消息:暫不投遞的消息,發送方已將消息成功發送到了MQ服務端,但是服務端未收到生產者對該消息的二次確認,此時該消息被標記成"暫不能投遞"狀態,處於該種狀態下的消息即半消息
    • 消息回查:由於網絡閃斷,生產者應用重啟等原因,導致某條事物消息的二次確認丟失,MQ服務端通過掃描發現某條消息長期處於半消息時,主要主動向消息生產者詢問該消息的最終狀態(Commit或Rollback),即消息回查
  • MQ分布式事物設計方案

image.png

  • MQ分布式事物消息設計
    • MQ事物消息設計事物消息作為一種異步確保型事物,將兩個事物分支通過MQ進行異步解耦,MQ事物消息的設計流程同樣借鑒了兩階段提交理論,整體交互流程如上圖
    1. 事物發起方首先發送prepare消息到MQ
    2. 在發送prepare消息成功后執行本地事物
    3. 根據本地事物執行結果返回commit或rollback
    4. 如果消息是rollback,MQ將刪除該prepare消息,不進行下發,如果是commit消息,MQ會將消息發送給consumer端
    5. 如果執行本地事物過程中,執行端掛掉,或者超時,,MQ服務器端將不停的詢問producer來獲取事物狀態
    6. consumer端的消費成功機制有MQ保證
  • 成本:
    • MQ需要支持半消息
    • MQ需要提供消息遍歷
    • 業務方需要提供回查接口
  • 業務方接入步驟

image.png

  • 優點
    • 通用
  • 缺點
    • 業務方需要提供回查接口,對業務侵入大
    • 發送消息非冪等
    • 消費端需要處理冪等

 

方案二:本地事物消息表

  • 本地操作和發送消息通過本地事物強一致性
    • 本地事物操作表
    • 本地事物消息表
      • mqMessages(msgid,content,topic,status)

image.png

  • 發送端消息不冪等
    • At least once (最少發一次)
    • Once Only (只發一次)
    • At more once(最多發一次)
  • 消費端處理消息冪等
    • 分布式鎖
  • A->B->C
    • A/B成功,C失敗
      • 記錄錯誤日志
      • 報警
      • 人工介入
  • 優點
    • 業務入侵小

相比於提供消息回查接口(RockectMQ)來說,實際異步場景還是本地消息事物表使用的比較多

 

同步場景分布式事物設計

  • 同步場景
    • 首頁推薦商品列表
      • 商品信息
      • 用戶信息
      • 社交信息
    • 購買商品
      • 下單->A
      • 減庫存->B
      • 支付->C

image.pngimage.png

通過業務邏輯層驅動

  • 解決方案
    • 基於異步補償的分布式事物
    • 架構設計的三大關鍵點

image.png

開始記錄調用請求的參數,如果失敗后基於參數做補償接口,接口需要保證冪等性

  • 總體架構設計

image.png

場景:A下單,B減庫存,C支付,在調用接口的時候,A先走Proxy存入事物ID,狀態,參數等信息,然后執行本地事物,接着B,C走同樣的流程如果都成功,那么事物狀態改成2,也就是成功,如果在C失敗的時候可以更具參數,事物ID對A,B進行補償

業務邏輯層Proxy設計(基於AOP實現)

    • 邏輯層調用上加上事物注解@Around("execution(**(..)) && @annotation(TX)")
    • Proxy在真正業務邏輯被調用之前,生成一個全局唯一TXID標示事務組,TXID保存在ThreadLocal變量中,方法開始前寫入,完成后清除,並向遠端數據庫寫入TXID並把事務組制成開始狀態
    • 業務邏輯層調用數據訪問層之前,通過RPCProxy代理記錄,當前調用請求參數
    • 如果業務正常,調用完成后,當前方法的調用記錄刪除或者存檔
    • 如果業務異常,查詢調用鏈反向補償

image.png

  • 數據訪問層設計
    • 原子接口
    • 補償接口
      • 誰來提供?
        • 業務方提供
      • 冪等性保證
        • 采用本地資源鎖,鎖定唯一資源
    • 基於原則接口方法,在方法名加注解標注補償方法名
    • @Compensable(cancelMethod = "cancelRecord")

image.pngimage.png

  • 分布式事物補償服務
    • 事物組表(數據庫表TDB)    
      • 記錄事物組狀態
      • txid state timestamp
    • 事物調用組表(數據庫表TDB)
      • 記錄事物組內的每一次調用,以及相關參數
      • txid actionid callmethod pramatype params
    • 補償策略
      • 調用執行失敗,修改事物組狀態
      • 分布式事物補償服務異步執行補償

分布式事物成功案例

  • 二手交易創建訂單事務組正常流程
    • 鎖庫存->減紅包->創建訂單
  • 代理層透明記錄調用請求參數
    • 記錄事物域的開始與結束
    • 在所有遠程調用成功時
    • 對業務邏輯不做侵入

image.png

分布式事物失敗案例

  • 二手交易創建訂單事務組異常流程
    • 微服務數據訪問層失敗,代理更改事務組狀態
    • 微服務業務正常執行
    • 事物補償服務異步執行補償

image.png

好了,到這里分布式事物也就寫完了..休息一下,,哎,又到了找工作的時候了,有需要可以聯系我


免責聲明!

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



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