.Net Core with 微服務 – 分散式事務 – 2PC、3PC

最近比較忙,好久沒更新了。這次我們來聊一聊分散式事務。
在微服務體系下,我們的應用被分割成多個服務,每個服務都配置一個資料庫。如果我們的服務劃分的不夠完美,那麼為了完成業務會出現非常多的跨庫事務。即使按照 DDD 的原則來切分服務還是免不了有的業務場景需要多個業務同時提交成功或者同時回滾的場景。比如會員使用積分下訂單這個場景,那麼會員服務的積分扣減需要跟訂單下單成功同時完成。如果下單成功,但是扣減積分介面失敗,那麼就會造成數據的不一致性。這個時候我們就需要使用分散式事務來保證數據的一致性。
由於分散式事務要介紹的東西比較多,這一篇只介紹 2PC、3PC 的基本概念,所以 .net 相關的內容大概也只會出現在標題上一次,笑哭。

什麼是 2PC

2PC 既 Two-phase Commit ,中文翻譯為二階段提交。2PC 要求每個事務的參與方都把一個事務抽象成2個階段。下面大概分析下 2PC 事務的流程。
首先提出2個概念:

  1. 參與方
    分散式事務中所有需要同時進入事務的業務方。
  2. 協調器
    分散式環境下為了對多個事務參與方進行統一的調度管理,我們需要一個調度器。

階段一

事務開始後,協調器下達事務開始的命令,每個參與方收到命令後開始執行準備階段(Prepare phase),所謂準備階段就是執行本地事物,這個時候資源被鎖定,但是不進行提交。如果這個階段沒有發生異常,那麼參與方會通知協調器「執行成功」。如果某個參與方在這個階段失敗了,那麼同樣通知協調器「執行失敗」,協調器會給所有參與方發布回滾的命令。參與方在收到「回滾」命令後執行回滾操作。

階段二

如果所有的參與方在階段一全部響應成功,那麼協調器就會給每個參與方發布執行提交操作的命令。參與方收到提交命令後開始嘗試進行事務提交。如果事務提交成功,參與方會通知協調器「提交成功」。待到所有的參與方全部回復「提交成功」,那麼本次事務成功執行。

到這裡我們可以看到 2PC 模型跟資料庫的事務模型是高度契合的,所以 2PC 經常用來把多個資料庫事物包裝成一個分散式事務的場景。事實上大多數資料庫如:oracle,mysql等自己已經實現了基於XA協議的2PC 事務。

2PC 的問題

  1. 在一階段,假設參與方A執行事務成功並通知了協調器,參與方B執行失敗,由於網路的問題一直無法上報給協調器,這個時候會造成參與方A事務一直是等待提交狀態,阻塞整個業務。這個時候就需要引入超時機制,在一定時間內沒收到協調器的指令後直接回滾事務。
  2. 在一階段,假設參與方A執行事務成功並通知了協調器,參與方B執行成功,由於網路的問題一直無法上報給協調器,這個時候會造成參與方A、參與方B事務一直是等待提交狀態,阻塞整個業務。這個時候不光在參與方A一側需要引入超時機制,在參與方B同樣需要進入超時機制來自動回滾事務。
  3. 在二階段,如果參與方A提交成功,參與方B因為某些原因提交失敗,或者是伺服器宕機或者是網路原因B一致沒有收到提交的指令,這個時候就會造成數據不一致,這種情況 2PC 幾乎沒有補償能力,只能依靠後期手動修複數據。
  4. 如果協調器在一階段中間掛了,那麼跟以上1、2情況類似,需要通過超時機制來補償。
  5. 如果協調器在二階段中間掛了,比如只給參與方A發送了提交請求,那麼就會造成以上問題3類似的問題,造成數據不一致。
  6. 2PC 因為依賴資料庫本地事務,我們知道事務一旦開啟就會阻塞後面的業務執行。所以該方法在並發高的情況下會有比較大的性能問題。而且他所阻塞的時間遠遠高於單機事務,因為它所耗的時間取決於執行時間最長的那個參與方所執行的事務。

3PC

由於 2PC 的眾多問題,又有人發明了 3PC 事務。
3PC 事務是對 2PC 的一次改進:

  1. 首先引入了超時機制避免事務長時間阻塞。
  2. 3PC 在 2PC 的 Prepare phase 階段之前又加入了一個階段叫做 CanCommit 階段。現在3個階段分別是:CanCommit、PreCommit、DoCommit 。後兩個階段大致可以映射到 2PC 的一階段跟二階段。那麼CanCommit 階段是幹嘛的呢?CanCommit 只是一次預檢,協調器先問一下各個參與者是否可以進行事務,同時也校驗一下當前的網路是否正常,參與者伺服器有沒有宕機。經過這一次校驗後,至少可以比 2PC 安全一點,減少因為當前網路故障服務宕機帶來的故障的概率。但是 3PC 任然無法完全解決問題,在 DoCommit 命令發布後,依然有可能部分參與者提交成功,部分失敗,2PC 數據不一致的問題 3PC 依然無法避免。

總結

以上簡單介紹了 2PC、3PC 分散式事務的原理。我們可以看到 2PC 在理想情況下是可以保證數據一致性的。但是在複雜的生產環境下伺服器宕機、網路故障的情況時有發生,最終導致數據的不一致,並且 2PC 的性能也差強人意。3PC 雖然改進了 2PC 的一些缺點,但是仍然沒有解決掉最致命的數據不一致的問題、以及性能的問題。所以 2PC、3PC 並不是分散式事務的首選方案。那麼下期我們將繼續這個話題,繼續介紹 TCC 分散式事務。

相關文章

NET Core with 微服務 – 什麼是微服務
.Net Core with 微服務 – 架構圖
.Net Core with 微服務 – Ocelot 網關
.Net Core with 微服務 – Consul 註冊中心
.Net Core with 微服務 – Seq 日誌聚合
.Net Core with 微服務 – Elastic APM
.Net Core with 微服務 – Consul 配置中心
.Net Core with 微服務 – Polly 熔斷降級

關注我的公眾號一起玩轉技術