一句話總結:分布式事務業界主流方案:兩階段提交方案(包括XA方案和TCC方案)、消息隊列方案。
1、兩階段提交方案
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消息丟失,重試進行解決
2)引入對賬機制,定時對賬,異常時觸發對賬
3)騰訊雲金融級TDSQL XA方案設計思路,對於參與者,若未收到commit/rollback消息或收到執行異常,需有一套機制保證參與者無論如何都能成功執行事務。
這套機制需要兩個條件:
1、協調者在發出commit/rollback命令之前記錄事務ID和事務狀態
2、參與者上有個獨立守護進程,此進程不會掛掉(掛掉就重啟),定時檢查參與者有prepare狀態數據並超過一定時間后,此進程就去協調者上守護進程查詢事務狀態(不斷查詢,網絡中斷退出集群),查詢到狀態后在本節點上執行事務,通常prepare成功commit/rollback會成功,若不成功該進程也要去解除不成功的因素如解除死鎖讓其成功
TCC方案優化思路網上也有人整理,參考下圖:
4)第3點優化方案較復雜,通常兩階段提交方案在多次重試無效后,就告警由人工介入
2、消息隊列方案
消息隊列方案主要是解決兩階段提交阻塞式,性能不高的問題。它的思路是分段執行,各個參與者先各自執行,再由異步消息來確保最終一致性。整個過程沒有同步阻塞,提高了並發和性能。思路有點類似樂觀鎖,先假定各個參與者都能成功執行。
消息隊列方案為了保證最終一致性,事務狀態的憑據很重要,實在不行最后人工介入查看憑據,需要業務獨立創建一張表存儲,類似狀態機機制,每個節點寫業務表和寫事務狀態表在同一個事務中,確保事務狀態寫成功。
正常流程發起方發出消息,其他參與者收到消息執行本地事務,執行成功向發起方返回執行成功消息,發起方收到消息在事務表中標識該參與者事務完成或刪除此事務信息。參與者執行失敗則發起回滾消息,此時其變為消息發起方,流程與前面一樣。
每個節點上起定時線程,檢查未處理完成或發出失敗的消息,重新發出消息,即重試機制和冪等性機制。
目前阿里雲的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
圖片來源網絡,侵刪