微服務架構中分布式事務解決方案總結


前言:最近,在家里養傷,由於博主騎自行車不小心摔跤了,給自己造成了影響,同時也給公司造成了影響,沒有按時報到。希望大家騎自行車時一定要小心,手里不要拿手機,還是那句話:道路千萬條,安全第一條,行車不規范,親人兩行淚。好了,這是血的教訓。今天的主題不是教如何騎自行車,哈哈哈。言歸正傳,利用在家養傷總結一下面試中經常問到的在微服務架構中如何解決分布式事務的問題。因為,這個問題,當時回答的不是太好,下來也查詢很多資料,算是總結一下學習的心得,如果有不對的地方還請大佬們能多多指點。

 

一、理論

首先這個問題是出現在微服務架構、分布式環境中的,在單機系統中是不用考慮這個問題的,首先我們來看下分布式系統的CAP原則和BASE理論。

 

 

 我們知道,這個三個特征最多只能滿足兩個,三者不可兼得。一致性:所有節點在同一時間點所有的數據都是一致的。可用性:在任何時候分布式系統總是可以成功讀和寫。分區容忍性:在某些節點因為網絡故障時,仍然能夠滿足一致性和可用性的服務。

選擇CA:放棄p 等同於放棄分布式系統,只存在於單機系統
選擇CP:也就是選擇分區容忍性和強一致性,允許在極端情況下出現暫時服務的不可用。
選擇AP:允許出現數據的短時不一致,在服務注冊的場景短期的數據不一致,不會對服務造成影響。因此采用AP原則的注冊中心才是微服務比較合適的選擇。

然后,介紹一下BASE理論,如圖底部的詞匯,BASE指Basically Available 基本可用,Soft-state 軟狀態(狀態允許有短時間不同步,異步), Eventual Consistency 最終一致性,它是對CAP中一致性和可用性的權衡的結果,BASE的核心思想是即使無法做到強一致性,也可以根據系統特性,采用適當的方式達到最終一致性。基於這樣的理論知識,我們只要做到最終一致性就可以解決分布式系統中的問題了。在分布式系統中,最重要的是滿足業務需求,而不是追求抽象、絕對的系統特性。

如果感覺還是不太明白建議參考CAP框架作者的這篇文章:https://www.cnblogs.com/savorboard/p/base-an-acid-alternative.html

 

二、場景

一圖勝千言:

 

 

三、解決方案分析

解決方案:

(1)剛性事務

  全局事務(標准的分布式事務)

  優點:嚴格的ACID;

  缺點:效率非常低(微服務架構下已經不太合適)

  原因:1)全局事務方式下,全局事務管理器(TM)通過XA接口使用二階段提交協議(2pc)與資源層(如數據庫進行交互)。使用全局事務,數據被lock的時間跨整個事務,直到全局事務結束。

     2)2pc是反可伸縮模式,在事務處理過程中,參與者需要一直持有資源直到整個分布式事務結束,這樣當業務規模越來越大的情況下,2pc的局限性就越來越明顯,系統可伸縮性就會變的很差。

     3)與本地事務相比,XA協議的系統開銷相當大,因而應當謹慎考慮是否確實需要分布式事務。而且只有支持XA協議的資源才能參與分布式事務。

    

(2)柔性事務

  可靠消息最終一致性(異步確保型)

  

 

   

  TCC(兩階段型、補償型)【略】

  最大努力通知(非可靠消息、定期校對)【略】

 

我們現在知道有這么多解決分布式事務的方案,我們能否自己去實現一個分布式事務框架呢?假如我們選擇柔性事務中的,可靠消息最終一致(異步確保型)這種方案來實現就不得不涉及到消息中間件的使用了,消息中間價在分布式系統中的主要作用是,異步通訊、解耦、削峰填谷等。如下圖所示:

 

 如果按照上面的圖,大家可能認為它很簡單呀,一個發送消息,一個接受消息。但是在分布式系統中,需要通過網絡進行通信的,就引入了數據傳輸的不確定性,也就是CAP理論中的P(分區容錯性的問題),如下圖所示:

 

 很顯然,正是因為跨網絡,就會產生消息發送不一致的問題,也就是說,如果我的業務操作成功,那么有這個業務操作所產生的消息一定要成功投遞出去,否則就丟失消息。那么我們該怎么解決這樣的問題呢?

也就是如何保障消息發送一致性?通常我們在使用消息隊列來處理業務都會遇到這樣的場景:

public  void  CompleteOrder()
{
    //訂單處理
   orderService.OrderProcess();
   //財務處理(發送消息)  
   ......  

}

 

(1)如果業務操作成功,執行消息發送前應用故障,消息發送不去去,導致消息丟失(訂單系統和財務系統數據產生不一致)

(2)如果業務操作成功,應用正常,但消息系統故障或者網絡故障,也會導致消息發送不出去(訂單系統和財務系統數據產生不一致)。

另外一種處理方案:

public  void  CompleteOrder()
{
   
   //財務處理(發送消息)  
   ......  

 //訂單處理
   orderService.OrderProcess();

}

 

也就是,我先發送消息再處理訂單,這種做法更不可控了,消息發送出去了,但是訂單處理失敗了(導致訂單和財務系統數據的不一致),記住在處理這種場景,一定是業務數據先入庫,再發送消息的。

貌似這兩種方式都不能保證業務數據的一致性,當然,我們可以借助JMS標准中的XA協議方式來保證消息發送的一致性,但是這種方式引入了XA,違背了柔性事務的初衷,會帶來很多局限性:

(1)要求業務操作的資源(也就是數據庫)必須支持XA協議(並不是所有的數據庫都支持XA)

(2)兩階段提交協議的成本

(3)持久化成本等DTP模型的局限性(全局鎖、成本高、性能低)

另外一種變通的做法如下:(這種方案只是解決的業務處理成功,消息一定能發送到消息中間件中)

 

 問題:

(1)上面的消息發送一致性方案的正向流程是可行的,但是如果遇到異常流程該怎么處理?

(2)消息發送到消息中間件能得到保障,但是消息的准確消費又如何保障呢?

(3)有沒有支持這種發送一致性流程的現成消息中間件?

 先來聊聊問題(1),有哪些場景會出現異常,如下圖所示:

 

 從主動應用方(生產者)來分析:

(1)預發消息失敗,消息未進行存儲,業務操作未執行(可能的原因:主動方應用、網絡、消息中間件、消息存儲等),這種場景不會出現不一致性。

(2)預發送消息后,主動方應用沒有收到返回消息存儲結果,可能的狀態有:消息未進行存儲,業務操作未執行(不會出現不一致性);如果消息已進行存儲【待確認】,業務操作未執行,會出現不一致性。

(3)收到消息存儲成功的返回結果,但未執行業務操作就失敗,可能的狀態有:消息已進行存儲【待確認】,業務操作未執行,會出現不一致性的問題。

 從消息中間件的角度分析:

(1)消息中間件沒有收到主動方應用的業務操作處理結果,可能的狀態:消息已經存儲(待確認),業務操作未執行(或者業務操作出錯回滾了),會出現數據的不一致性問題;如果消息已經存儲(待確認),業務操作成功,也會出現數據的不一致性。

(2)消息中間件收到業務操作結果(成功/失敗),但處理消息存儲中的消息狀態失敗,可能的狀態:消息已經存儲(待確認),業務操作未執行(或業務操作出錯回滾了),會出現數據的不一致性問題;如果消息已經存儲(待確認),業務操作成功,也會出現數據的不一致性問題。

 

那我們該如何處理這樣的異常問題呢?如下圖所示:

 

 這樣就可以處理異常的流程,有人可能會說,異常處理流程也可能發生異常呀,其實大家認真看的話,異常處理基本上都是查詢,如果查詢出現了異常,定時補救也是可以的。

總結:關於上面異常處理總結

(1)消息未進存儲,業務操作未執行,不會出現一致性問題。

(2)消息已進行存儲(待確認),業務操作未執行,會出現一致性問題,異常處理手段,確認業務操作結果,處理消息【刪除消息】

(3)消息已進行存儲(待確認),業務操作成功,會出現一致性問題,異常處理手段,確認業務操作結果,處理消息【更新消息狀態,執行消息投遞】

 

對於問題(3)有沒有現成的消息中間件支持消息發送一致性,答案是:沒有。是因為常用的MQ隊列消息的處理流程無法實現消息發送一致性,因此直接使用現成的MQ中間件產品無法實現可靠消息最終一致性的分布式解決方案。

對於問題(2)消息發送到消息中間件能得到保障,但是消息的准確消費又如何保障呢?

以前的流程,如下圖所示:

 

 紅框圈住的就是消息的消費流程,在這個流程中,任何一個環節都有可能出問題具體到下面這張圖:

 

 那我們如何處理,這些異常呢?處理的方法有很多,這里列出常規的做法:對於未確認的消息,采用按照規則重新投遞的方式進行處理。這里就不介紹了,  當然,我們需要處理極端情況:消息重發也得有次數限制,要不然就變成了死循環,對於超過重發次數的消息,進入到死信隊列,等待人工干預或者延后定期處理。同時也需要處理被動方在處理業務時要實現冪等操作。

 

四、總結

好了,暫時分享到這里吧,雖然在分布式系統中已經有現成的框架,比如.net core 中的 CAP框架,非常的不錯,我們生產環境中已經用了很長時間,框架能幫助我們解決實際場景下的問題,但是我們也要明白框架背后的原理,明白大概的原理,再去看CAP的源碼,你會恍然大悟的!哈哈哈哈。

 

 

 

 

參考資料:

 

龍果學院   吳水成老師   《微服務架構的分布式事務解決方案》  https://www.roncoo.com/details/7ae3d7eddc4742f78b0548aa8bd9ccdb

CAP框架作者  楊老師   https://www.cnblogs.com/savorboard/p/base-an-acid-alternative.html

 

 

 

 

作者:郭崢

出處:http://www.cnblogs.com/runningsmallguo/

本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM