目錄
- 一、分布式事務
- 二、分布式事務的解決方案
- 1. 全局事務
- (1)DTP模型
- (2) 兩階段提交協議(2PC)
- 原理
- 二階段提交的缺點
- (3)三階段提交協議(3PC)
- 原理
- 2. 基于可靠消息服務
- 3. 最大努力通知
- 4. TCC
一、分布式事務
事務指的是一組操作,要么全部成功,要么全部失敗。事務有四個特性ACID,具體涵義參考數據庫原理這篇博客
這里舉一個銀行轉賬的例子來說明本地事務和分布式事務的區別。
本地事務可依賴數據庫本身提供的事務特性來實現,因此以下邏輯可以控制本地事務:
begin transaction;//1.本地數據庫操作:張三減少金額//2.本地數據庫操作:李四增加金額
commit transation;
但是在分布式環境下,會變成下邊這樣:
begin transaction;//1.本地數據庫操作:張三減少金額//2.遠程調用:讓李四增加金額
commit transation;
可以設想,當遠程調用讓李四增加金額成功了,由于網絡問題遠程調用并沒有返回,此時本地事務提交失敗就回滾了張三減少金額的操作,此時張三和李四的數據就不一致了。
? 因此在分布式架構的基礎上,傳統數據庫事務就無法使用了,張三和李四的賬戶不在一個數據庫中甚至不在一個應用系統里,實現轉賬事務需要通過遠程調用,由于網絡問題就會導致分布式事務問題。
二、分布式事務的解決方案
1. 全局事務
(1)DTP模型
DTP模型規定了要實現分布式事務的體系結構,包含多個協議、算法和機制等,以確保分布式環境下的事務能夠以一致和可靠的方式執行。
它規定了要實現分布式事務,需要三種角色:
-
AP:Application 應用系統它就是我們開發的業務系統,在我們開發的過程中,可以使用資源管理器提供的事務接口來實現分布式事務。
-
TM:Transaction Manager 事務管理器
- 提供分布式事務的操作接口供業務系統調用。這些接口稱為TX接口
- 事務管理器管理著所有的資源管理器,通過它們提供的XA接口來同一調度這些資源管理器
- DTP只是一套實現分布式事務的規范,并沒有定義具體如何實現分布式事務,可采用2PC、3PC、Paxos等協議實現
-
RM:Resource Manager 資源管理器
- 能夠提供數據服務的對象都可以是資源管理器,比如:數據庫、消息中間件、緩存等
- 資源管理器能夠提供單數據庫的事務能力,它們通過XA接口,將本數據庫的提交、回滾等能力提供給事務管理器調用,以幫助事務管理器實現分布式的事務管理
- XA是DTP模型定義的接口,用于向事務管理器提供該資源管理器(該數據庫)的提交、回滾等能力
- DTP只是一套實現分布式事務的規范,RM具體的實現是由數據庫廠商來完成的
DTP主要側重于業務實現分布式事務時的體系結構,而后面介紹的2PC和3PC則側重于實現的邏輯,相當于DTP是殼,而2PC/3PC等協議是核。
舉個例子,在通信的場景下,DTP的作用相當于定義了通信中需要有發送方和接受方,要求這兩方都需要有發送和接收的能力,要求通過一系列的通信方式使得他們能正常通話。而2PC/3PC則是相當于定義了具體的通信邏輯,比如TCP三次握手和IP協議等等。
(2) 兩階段提交協議(2PC)
原理
兩階段提交又稱 2PC,是一個非常經典的強一致、中心化的原子提交協議。兩階段提交協議經常用來實現分布式事務。
2PC協議中,節點分為兩種角色
- 事務協調者:協調事務的功能,通常一個系統中只有一個
- 事務參與者:一般包含多個
將整個事務流程分為兩個階段:
- 準備階段(Prepare phase):事務協調者給每個參與者發送Prepare消息,每個參與者要么直接返回失敗(如權限驗證失敗),要么在本地執行事務操作(如寫本地的redo和undo日志),但不提交,到達一種“萬事俱備,只欠東風”的狀態
- 事務詢問:協調者向所有的參與者發送事務預處理請求,并開始等待各參與者的響應
- 執行本地事務:各個參與者節點執行本地事務操作,但在執行完成后并不會真正提交數據庫本地事務
- 各參與者向協調者反饋事務詢問的響應:各參與者根據自身事務執行情況反饋,成功反饋yes,失敗返回no
- 提交階段(commit phase):根據不同的情況做出相應的操作
- 所有的參與者反饋給協調者的信息都是 Yes,則執行事務提交
- 有一個或者多個返回 No,或有超時,回滾
二階段提交的缺點
- 性能問題:執行過程中,所有參與節點都是事務阻塞型的。當參與者占有公共資源時,其他第三方節點訪問公共資源不得不處于阻塞狀態。也就是說從投票階段到提交階段完成這段時間,資源是被鎖住的,對性能影響比較大。
- 單點故障:主要指協調者發生故障,這種情況下參與者會一直阻塞下去,尤其在第二階段,協調者發生故障,那么所有的參與者還都處于鎖定事務資源的狀態中,而無法繼續完成事務操作。
- 網絡分區是會數據不一致:階段二中,當協調者向參與者發送commit請求之后,發生了網絡分區,那就只有一部分參與者執行了commit,產生了數據不一致的情況
(3)三階段提交協議(3PC)
原理
三階段提交(Three-phase commit)是二階段提交(2PC)的改進版本。三階段提交協議(3PC)主要是為了解決兩階段提交協議的單點故障阻塞問題,2PC 存在的問題是當協調者崩潰時,參與者可能在協調者恢復之前保持阻塞。
增加的改進措施:
- 增加超時機制:不只有協調者能感知參與者的超時,參與者也能感知協調者的超時,當其超時時,就釋放自身的資源,不再繼續阻塞
- 在準備階段前多加了一個準備階段,變成有 CanCommit、PreCommit、DoCommit 三個階段
過程:
- CanCommit 階段:協調者向參與者發送commit請求,參與者如果可以提交就返回Yes響應,否則返回No響應,這個過程很輕量,比如嘗試獲取數據庫鎖
- 事務詢問:協調者向參與者發送CanCommit請求。詢問是否可以執行事務提交操作。然后開始等待參與者的響應
- 響應反饋:參與者接到CanCommit請求之后,正常情況下,如果其自身認為可以順利執行事務,則返回Yes響應,并進入預備狀態。否則反饋No
- PreCommit階段:根據第一階段接受到的結果采取相應操作
- 都是yes,進行預執行,參與者進行事務預提交,相應反饋
- 有no或超時,參與者中斷事務,釋放其資源
- doCommit階段:該階段進行真正的事務提交,也可以分為以下兩種情況
- 執行提交:協調者發送事務commit通知,參與者執行commit操作,反饋
- 中斷事務:協調者沒有收到所有的ack,或者有超時情況,中斷事務,參與者進行事務的rollback
幾種情況示意圖如下
2. 基于可靠消息服務
通過消息中間件來實現。
假設有A和B兩個系統,分別可以處理任務A和任務B。此時系統A中存在一個業務流程,需要將任務A和任務B在同一個事務中處理。下面來介紹基于消息中間件來實現這種分布式事務。
- 在系統A處理任務A前,首先向消息中間件發送一條消息
- 消息中間件收到后將該條消息持久化,但并不投遞。此時下游系統B仍然不知道該條消息的存在。
- 消息中間件持久化成功后,便向系統A返回一個確認應答;
- 系統A收到確認應答后,則可以開始處理任務A;
- 任務A處理完成后,向消息中間件發送Commit請求。該請求發送完成后,對系統A而言,該事務的處理過程就結束了,此時它可以處理別的任務了。
- 消息中間件收到Commit指令后,便向系統B投遞該消息,從而觸發任務B的執行;
- 當任務B執行完成后,系統B向消息中間件返回一個確認應答,告訴消息中間件該消息已經成功消費,此時,這個分布式事務完成。
總結一下上述過程的特點,
- 消息中間件扮演者分布式事務協調者的角色。
- 系統A完成任務A后,到任務B執行完成之間,會存在一定的時間差。在這個時間差內,整個系統處于數據不一致的狀態,但這短暫的不一致性是可以接受的,因為經過短暫的時間后,系統又可以保持數據一致性,滿足BASE理論。
上述過程中,如果任務A處理失敗,那么需要進入回滾流程,如下圖所示:
- 向消息中間件發送Rollback請求。和發送Commit請求一樣,系統A發完之后便可以認為回滾已經完成,它便可以去做其他的事情。
- 消息中間件收到回滾請求后,直接將該消息丟棄,而不投遞給系統B,從而不會觸發系統B的任務B
Commit和Rollback指令都有可能在傳輸途中丟失,當出現這種情況的時候,消息中間件通過超時詢問機制保證事務的一致性
詢問的結果有三種
- 提交若獲得的狀態是“提交”,則將該消息投遞給系統B。
- 回滾若獲得的狀態是“回滾”,則直接將條消息丟棄。
- 處理中若獲得的狀態是“處理中”,則繼續等待。
為保證一致性,消息中間件必須確保發送的消息能被下游接收到,如果超時就會重傳,直到得到應答
3. 最大努力通知
是最簡單的一種柔性事務,適用于一些最終一致性時間敏感度低的業務。
最大努力通知型的實現方案,一般符合以下特點:
? 1、不可靠消息:業務活動主動方,在完成業務處理之后,向業務活動的被動方發送消息,直到通知N次后不再通知,允許消息丟失(不可靠消息)。
? 2、定期校對:業務活動的被動方,根據定時策略,向業務活動主動方查詢(主動方提供查詢接口),恢復丟失的業務消息。
4. TCC
TCC分別對應Try、Confirm和Cancel三種操作
- Try:預留業務資源
- Confirm:確認執行業務操作
- Cancel:取消執行業務操作
TCC實際上把數據庫層的二階段提交上提到了應用層來實現,即Try、Confirm和Cancel操作功能需業務提供