一句話總結:分佈式事務業界主流方案:兩階段提交方案(包括XA方案和TCC方案)、消息隊列方案。html
一、兩階段提交方案sql
1.1 XA方案數據庫
XA協議流程能夠查看做者另外一篇「2PC兩階段提交協議」,XA方案是資源層的兩階段提交,一般應用於多數據庫操做的場景,如Mysql 5.5版本以上Innodb引擎原生支持XA。應用層可搭配Spring JTA對接數據庫XA,開發人員便可無需處理多庫事務,交給框架和DB處理。網絡
1.2 TCC方案併發
TCC方案是應用層的兩階段提交,一般應用於徹底獨立的多個系統間經過RPC調用,須要提供逆操做接口用於回滾。甚至做者認爲TCC比兩階段提交還簡單,能夠將try和confirm合併成一階段提交,TCC在try操做完後默認認爲commit都會成功。框架
1.3 兩階段提交方案優化異步
咱們知道兩階段提交協議的問題在於,協調者在第二階段發出commit/rollback後就無論了,這裏能夠優化:分佈式
1)超時重試,接口冪等性(基於事務ID)。優化網絡短暫中斷場景,單次commit/rollback消息丟失,重試進行解決post
2)引入對帳機制,定時對帳,異常時觸發對帳性能
3)騰訊雲金融級TDSQL XA方案設計思路,對於參與者,若未收到commit/rollback消息或收到執行異常,需有一套機制保證參與者不管如何都能成功執行事務。
這套機制須要兩個條件:
一、協調者在發出commit/rollback命令以前記錄事務ID和事務狀態
二、參與者上有個獨立守護進程,此進程不會掛掉(掛掉就重啓),定時檢查參與者有prepare狀態數據並超過必定時間後,此進程就去協調者上守護進程查詢事務狀態(不斷查詢,網絡中斷退出集羣),查詢到狀態後在本節點上執行事務,一般prepare成功commit/rollback會成功,若不成功該進程也要去解除不成功的因素如解除死鎖讓其成功
TCC方案優化思路網上也有人整理,參考下圖:
4)第3點優化方案較複雜,一般兩階段提交方案在屢次重試無效後,就告警由人工介入
二、消息隊列方案
消息隊列方案主要是解決兩階段提交阻塞式,性能不高的問題。它的思路是分段執行,各個參與者先各自執行,再由異步消息來確保最終一致性。整個過程沒有同步阻塞,提升了併發和性能。思路有點相似樂觀鎖,先假定各個參與者都能成功執行。
消息隊列方案爲了保證最終一致性,事務狀態的憑據很重要,實在不行最後人工介入查看憑據,須要業務獨立建立一張表存儲,相似狀態機機制,每一個節點寫業務表和寫事務狀態表在同一個事務中,確保事務狀態寫成功。
正常流程發起方發出消息,其餘參與者收到消息執行本地事務,執行成功向發起方返回執行成功消息,發起方收到消息在事務表中標識該參與者事務完成或刪除此事務信息。參與者執行失敗則發起回滾消息,此時其變爲消息發起方,流程與前面同樣。
每一個節點上起定時線程,檢查未處理完成或發出失敗的消息,從新發出消息,即重試機制和冪等性機制。
目前阿里雲的RocketMQ提供了無需業務耦合便可事務的消息隊列,主要優化了事務狀態存儲和查詢、類兩階段的消息發出機制,即先prepare消息,當收到commit後消息才發出等。有興趣可深刻去研究下。
https://www.aliyun.com/product/ons?spm=5176.8142029.cloudEssentials.80.e9396d3ehA6Jv5
總結:
沒有最好的技術,只有最合適的技術。這三種方案適用的場景都不同。對於併發不高,對資源層一般是數據庫均由訪問權限的分佈式系統,建議採用Spring JTA + DB XA方案。對於併發不高,互相獨立的分佈式系統,建議採用TCC方案。對於併發高的分佈式系統,建議考慮消息隊列方案。
引用:
https://www.cnblogs.com/savorboard/p/distributed-system-transaction-consistency.html
https://blog.csdn.net/u010412301/article/details/78410933
圖片來源網絡,侵刪