這裡我們一起來學習下分布式事務,大概有以下幾個學習内容:
1、分布式事務産生的背景
2、解決分布式事務基本思想Base和CAP理論
3、柔性事務與剛性事務差別
4、了解分布式事務核心思想軟狀态和最終一緻性思想
5、分布式事務常見解決方案
5.1 傳統模式使用Jta+Atomikos
5.2 2PC與3PC實作的差別
5.3 使用阿裡巴巴TCC補償架構(用于Dubbo)
5.4 使用可靠消息模式
5.5 使用LCN架構解決分布式事務
5.6 阿裡GTS架構解決分布式事務
分布式事務産生的背景
在微服務環境下,因為會根據不同的業務會拆分成不同的服務,比如會員服務、訂單服務、商品服務等,讓專業的人專業的事情,每個服務都有自己獨立的資料庫,并且是獨立運作,互不影響。
服務與服務之間通訊采用RPC遠端調用技術,但是每個服務中都有自己獨立的資料源,即自己獨立的本地事務。兩個服務互相通訊的時候,兩個本地事務互不影響,進而出現分布式事務産生的原因。
傳統項目大部分情況下,不會産生分布式事務,但是在項目中如果采用多資料源方式,就會出現分布式事務。還有另外一種就是不同業務拆分成不同服務,不同服務有自己的獨立資料庫,這種也需要分布式事務。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL9UERPlXT65keJRVT3V1MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLwEzN0ITMwkDMzETNwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
本地事務有效範圍在同一個jdbc裡面,不同jdbc,事務是隔離的。同一個資料庫,不同jdbc,事務也是隔離的。
截圖裡的場景是兩個微服務,一個是下單,一個是扣庫存。如果這兩個服務調用完,出現int i=1/0;出現程式錯誤。這種就需要分布式事務了。
如果是在兩個微服務的内部處理邏輯,出現程式出錯,比如下面,在扣庫存的服務裡,int i=1/0;出現異常。這種就不是分布式事務異常。這種情況,完全可以等庫存服務傳回狀态碼,判斷對錯,如果錯誤,就手動復原事務。
ACID酸堿平衡理論
需要了解一些名詞,CAP與Base理論、柔性事務與剛性事務、了解最終一緻性思想、JTA+XA、兩階段與三階段送出
CAP:帽子原理
CAP定律
這個定理的内容是指的是在一個分布式系統中、Consistency(一緻性)、 Availability(可用性)、Partition tolerance(分區容錯性),三者不可得兼。
一緻性(C)
在分布式系統中的所有資料備份,在同一時刻是否同樣的值。(等同于所有節點通路同一份最新的資料副本)
可用性(A)
在叢集中一部分節點故障後,叢集整體是否還能響應用戶端的讀寫請求。(對資料更新具備高可用性)
分區容錯性(P)
以實際效果而言,分區相當于對通信的時限要求。系統如果不能在時限内達成資料一緻性,就意味着發生了分區的情況,必須就目前操作在C和A之間做出選擇。
Base理論
BASE理論
BASE是Basically Available(基本可用)、Soft state(軟狀态)和 Eventually consistent(最終一緻性)三個短語的縮寫。BASE理論是對CAP中一緻性和可用性權衡的結果,其來源于對大規模網際網路系統分布式實踐的總結, 是基于CAP定理逐漸演化而來的。BASE理論的核心思想是:即使無法做到強一緻性,但每個應用都可以根據自身業務特點,采用适當的方式來使系統達到最終一緻性。
基本可用
基本可用是指分布式系統在出現不可預知故障的時候,允許損失部分可用性----注意,這絕不等價于系統不可用。比如:
(1)響應時間上的損失。正常情況下,一個線上搜尋引擎需要在0.5秒之内傳回給使用者相應的查詢結果,但由于出現故障,查詢結果的響應時間增加了1~2秒
(2)系統功能上的損失:正常情況下,在一個電子商務網站上進行購物的時候,消費者幾乎能夠順利完成每一筆訂單,但是在一些節日大促購物高峰的時候,由于消費者的購物行為激增,為了保護購物系統的穩定性,部分消費者可能會被引導到一個降級頁面
最終一緻性
最終一緻性強調的是所有的資料副本,在經過一段時間的同步之後,最終都能夠達到一個一緻的狀态。是以,最終一緻性的本質是需要系統保證最終資料能夠達到一緻,而不需要實時保證系統資料的強一緻性。
軟狀态
軟狀态指允許系統中的資料存在中間狀态,并認為該中間狀态的存在不會影響系統的整體可用性,即允許系統在不同節點的資料副本之間進行資料同步的過程存在延時
軟狀态案例就是支付,平台調用支付寶或者微信支付接口後,會重定向到同步位址,并且支付寶/微信支付會采用HttpClient,消息通知異步位址。這種情況下平台和支付寶就是兩個微服務,異步通知可以不用馬上通知,但是最終是要通知給平台,讓平台處理這筆訂單。如果異步通知失敗的情況下(異常或者通知接口出現延遲),支付寶會自動重試,重試過程中,會每隔一定時間(具體時間我也忘記了),補發異步通知,這個補發通知過程就是補償機制。或者平台可以調用支付寶接口,查詢支付狀态。這種方式,平台和支付寶,可能是不同開發語言的,這種可以用補償機制。但是分布式事務是不能跨語言的。
幂等性
一次和多次請求某一個資源對于資源本身應該具有同樣的結果(網絡逾時等問題除外)。也就是說,其任意多次執行對資源本身所産生的影響均與一次執行的影響相同。
這裡需要關注幾個重點:
- 幂等不僅僅隻是一次(或多次)請求對資源沒有副作用(比如查詢資料庫操作,沒有增删改,是以沒有對資料庫有任何影響)。
- 幂等還包括第一次請求的時候對資源産生了副作用,但是以後的多次請求都不會再對資源産生副作用。
- 幂等關注的是以後的多次請求是否對資源産生的副作用,而不關注結果。
- 網絡逾時等問題,不是幂等的讨論範圍。
幂等性是系統服務對外一種承諾(而不是實作),承諾隻要調用接口成功,外部多次調用對系統的影響是一緻的。聲明為幂等的服務會認為外部調用失敗是常态,并且失敗之後必然會有重試。
什麼情況下需要幂等
業務開發中,經常會遇到重複送出的情況,無論是由于網絡問題無法收到請求結果而重新發起請求,或是前端的操作抖動而造成重複送出情況。 在交易系統,支付系統這種重複送出造成的問題有尤其明顯,比如:
- 使用者在APP上連續點選了多次送出訂單,背景應該隻産生一個訂單;
- 向支付寶發起支付請求,由于網絡問題或系統BUG重發,支付寶應該隻扣一次錢。 很顯然,聲明幂等的服務認為,外部調用者會存在多次調用的情況,為了防止外部多次調用對系統資料狀态的發生多次改變,将服務設計成幂等性
柔性事務和剛性事務
兩階段送出協定
三段送出協定
兩段和三段送出的差別
SpringCloud結合LCN的幾個執行個體,我還沒總結,這裡放幾個demo
https://blog.csdn.net/fuck487/article/details/79937066
codingapi官方文檔:http://www.txlcn.org/zh-cn/docs/preface.html
LCN是這三個的首字母命名的:
鎖定事務單元(lock)
确認事務子產品狀态(confirm)
通知事務(notify)
5.0以後由于架構相容了LCN、TCC、TXC三種事務模式,為了避免區分LCN模式,特此将LCN分布式事務改名為TX-LCN分布式事務架構。
架構定位
LCN并不生産事務,LCN隻是本地事務的協調工
TX-LCN定位于一款事務協調性架構,架構其本身并不操作事務,而是基于對事務的協調進而達到事務一緻性的效果。
解決方案
在一個分布式系統下存在多個子產品協調來完成一次業務。那麼就存在一次業務事務下可能橫跨多種資料源節點的可能。TX-LCN将可以解決這樣的問題。
例如存在服務子產品A 、B、 C。A子產品是mysql作為資料源的服務,B子產品是基于redis作為資料源的服務,C子產品是基于mongo作為資料源的服務。若需要解決他們的事務一緻性就需要針對不同的節點采用不同的方案,并且統一協調完成分布式事務的處理。
方案:
若采用TX-LCN分布式事務架構,則可以将A子產品采用LCN模式、B/C采用TCC模式就能完美解決。
TX-LCN 主要有兩個子產品,Tx-Client(TC) Tx-Manager(TM). TC作為微服務下的依賴,TM是獨立的服務。
TC開啟分布式事務注解
在主類上使用
@EnableDistributedTransaction
@SpringBootApplication
@EnableDistributedTransaction
public class DemoAApplication {
public static void main(String[] args) {
SpringApplication.run(DemoDubboClientApplication.class, args);
}
}
TC微服務A業務方法配置
@Service
public class ServiceA {
@Autowired
private ValueDao valueDao; //本地db操作
@Autowired
private ServiceB serviceB;//遠端B子產品業務
@LcnTransaction //分布式事務注解
@Transactional //本地事務注解
public String execute(String value) throws BusinessException {
// step1. call remote service B
String result = serviceB.rpc(value); // (1)
// step2. local store operate. DTX commit if save success, rollback if not.
valueDao.save(value); // (2)
valueDao.saveBackup(value); // (3)
return result + " > " + "ok-A";
}
}
TC微服務B業務方法配置
@Service
public class ServiceB {
@Autowired
private ValueDao valueDao; //本地db操作
@LcnTransaction //分布式事務注解
@Transactional //本地事務注解
public String rpc(String value) throws BusinessException {
valueDao.save(value); // (4)
valueDao.saveBackup(value); // (5)
return "ok-B";
}
}
TC配置資訊說明
# 預設之配置為TM的本機預設端口
tx-lcn.client.manager-address=127.0.0.1:8070
事務控制原理
TX-LCN由兩大子產品組成, TxClient、TxManager,TxClient作為子產品的依賴架構,提供TX-LCN的标準支援,TxManager作為分布式事務的控制放。事務發起方或者參與反都由TxClient端來控制。
原理圖:
核心步驟
-
建立事務組
是指在事務發起方開始執行業務代碼之前先調用TxManager建立事務組對象,然後拿到事務标示GroupId的過程。
-
加入事務組
添加事務組是指參與方在執行完業務方法以後,将該子產品的事務資訊通知給TxManager的操作。
-
通知事務組
是指在發起方執行完業務代碼以後,将發起方執行結果狀态通知給TxManager,TxManager将根據事務最終狀态和事務組的資訊來通知相應的參與子產品送出或復原事務,并傳回結果給事務發起方。