日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【转】分布式事务的常见解决方案

發布時間:2023/12/10 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【转】分布式事务的常见解决方案 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、事務起步

1. 什么是事務

事務這種東西大家都耳熟能詳了,通常指由一組操作組成的一個工作單元,這一整個組合要么全部成功,要么全部失敗。

2. 本地事務

在計算機系統中,更多的是通過關系型數據庫來控制事務,這是利用數據庫本身的事務特性來實現的,因此叫數據庫事務,由于應用主要靠關系數據庫來控制事務,而數據庫和應用在同一服務器,所以基于關系型數據庫的事務又被稱為本地事務。

數據庫事務具有原子性(Atomacity)、一致性(Consistency)、隔離性(Isolation)和持久性(Durability)。

3. 分布式事務

隨著互聯網的快速發展,軟件系統由原來的單體應用轉變為分布式應用。分布式系統會把一個應用系統拆分為可獨立部署的多個服務,因此需要服務與服務之間遠程協作才能完成事務操作,這種分布式系統環境下由不同的服務之間通過網絡遠程協作完成事務稱為分布式事務。

以上面圖示舉例,當需要創建訂單的時候,將會涉及到訂單和庫存兩個操作。那么左圖操作兩個系統最終需要寫入兩個數據庫,我們需要保證分布式事務的一致性,這一點應該很容易理解,如果我們只創建了訂單而沒有去減少相應的庫存量,就會出現超賣的現象。同樣的像中間,雖然最終只涉及到一個數據庫,但是同樣需要保證一致性,右圖同理。

二、CAP理論與BASE理論

1. CAP理論

CAP是一致性(Consistency)、可用性(Availability)、分區容忍性(Partition Tolerance)三個詞語的縮寫,我們先簡單解釋下這三個詞語:

  • 一致性:服務A、B、C三個節點都存儲了用戶數據,要求三個節點在寫操作后的讀操作可以讀取到的數據都是最新的狀態;
  • 可用性:可用性即整個系統可以外提供服務;
  • 分區容忍性:分布式系統的節點往往都是分布在不同的機器上進行網絡隔離開的,這意味著必然會有網絡斷開的風險,這個網絡斷開的場景我們稱為分區容忍性;

那么在網絡分區出現,也就是有多個節點分布在不同的子網中時,如何實現一致性呢?過程大概如下:

  • 寫入主數據庫后將數據同步到從數據庫;
  • 寫入主數據庫后,在向數據庫同步期間要將從數據庫鎖定,待同步完成后再釋放鎖,以免在新數據寫入成功后,向從數據庫查詢到舊的數據。
  • 所以,如果我們在數據庫同步期間鎖定從數據庫,那么可用性就無法保證;如果不鎖定,那么就會有訪問向從數據庫讀取數據,可能會讀取到舊的數據,此時又無法保證一致性。

    所以用一句話概括CAP原理就是:當網絡分區發生時,一致性和可用性難以兩全。只能選擇CP或者AP。

    2. BASE理論

    2.1 強一致性和最終一致性

    CAP理論告訴我們一個分布式系統只能同時滿足CAP三項中的兩項,其中AP在實際應用中較多,AP即舍棄一致性,保證可用性和分區容忍性,但是在實際生產中很多場景也是需要實現一致性的。

    比如主數據庫向從數據庫中同步數據,即使不要一致性,但是最終也要將數據同步成功來保證數據一致,這種一致性和CAP中的一致性不同,CAP中的一致性是要求任何時間查詢每個節點數據都必須一致,它所強調的是一致性,但是最終一致性是允許在一段時間內各節點的數據不一致,但是經過一段時間每個節點的數據必須一致,它所強調的是最終一致性。

    2.2 Base理論介紹

    BASE 是 Basically Available(基本可用)、Soft State(軟狀態)和Eventually consistent(最終一致性)三個短語的縮寫。BASE理論是對CAP中AP的一個擴展,通過犧牲強一致性來獲得可用性,當出現故障允許部分不可用但要保核心功能可用,允許數據在一段時間內是不一致的,但是最終要達到一致狀態。滿足BASE理論的事務,我們稱之為“柔性事務”。

    • 基本可用:分布式系統在出現故障時,允許損失部分可用功能,保證核心功能可用。如,電商網站交易付款出現問題了,商品依然可以正常瀏覽;
    • 軟狀態:由于不要求強一致性,所以BASE允許系統中存在中間狀態(也叫軟狀態),這個狀態不影響系統可用性,如訂單的“支付中”、“數據同步中”等狀態,待數據最終一致后狀態改為“成功”狀態;
    • 最終一致:最終一致是指經過一段時間后,所有節點數據都會達成一致。如訂單的“支付中”狀態,最終會變成“支付成功”或者“支付失敗“,使訂單狀態與實際交易結果達成一致,但需要一定時間的延遲、等待。

    三、2PC兩階段提交

    2PC即兩階段提交(Two-phase Commit, 2PC),通過引入協調者(Coordinate)來協調參與者的行為,并最終決定這些參與者是否要真正執行事務。

    1. 運行過程

    1.1 準備階段

    協調者詢問參與者事務是否執行成功,參與者發回事務執行結果,如下圖所示:

    1.2 提交階段

    如果事務在每個參與者上都執行成功,事務協調者發送通知讓參與者提交事務;否則,協調者發送通知讓參與者回滾事務。

    注意:在準備階段,參與者只是執行了事務,但是并沒有提交,只有在提交階段接收到協調者發來的通知后,才進行提交或者回滾。

    2. XA方案

    2PC的傳統方案是在數據庫層面實現的,如Oracle和MySQL都支持2PC協議,為了統一標準和減少行業內不必要的對接成本,需要制定標準化的處理模型及接口標準,國際開放組織Open Group定義了分布式事務處理模型DTP(Distributed Transaction Processing Reference Model)。

    下面以新用戶注冊時送積分的案例來說明:

    執行流程如下:

  • 應用程序(AP)持有用戶庫和積分庫兩個數據源;
  • 應用程序(AP)通過TM通知用戶庫RM新增用戶,同時通知積分庫RM為該用戶新增積分,RM此時并未提交事務,此時用戶和積分資源鎖定;
  • TM收到執行回復,只要有一方失敗則分別向其他RM發起事務回滾,回滾完畢,資源鎖釋放;
  • TM收到執行回復,全部成功,此時向所有RM發起提交事務,提交完畢,資源鎖釋放。
  • DTP模型定義如下角色:

    • AP(Application Program):即應用程序,可以理解為使用DTP分布式事務的程序;
    • RM(Resource Program):即資源管理器,可以理解為事務的參與者,一般情況下是指一個數據庫實例,通過資源管理器對該數據庫進行控制,資源管理器控制著分支事務;
    • TM(Transaction Manager):事務管理器,負責協調和管理事務,事務管理器控制著全局事務,管理事務生命周期,并協調各個RM。全局事務是指分布式事務處理環境中,需要操作多個數據庫共同完成一個工作,這個工作即是一個全局事務。

    DTP模型定義TM和RM之間通訊的接口規范叫XA,簡單理解為數據庫提供的2PC接口協議,基于數據庫的XA協議來實現2PC又稱為XA方案

    以上三個交互角色之間的交互方式如下:

  • TM向AP提供應用程序編程接口,AP通過TM提交以及回滾事務;
  • TM中間件通過XA接口來通知RM數據庫事務的開始、結束以及提交、回滾等。
  • XA方案的缺陷:

    • 需要本地數據庫支持XA協議;
    • 資源鎖需要等待兩個階段結束才釋放,性能較差。

    3. Seata方案

    Seata是由阿里開源的分布式事務框架。傳統2PC的問題在Seata中得到了解決,通過對本地關系數據庫的分支事務的協調來驅動完成全局事務,是工作在應用層的中間件。主要優點是性能較好,且不長時間占用連接資源,以高效且對事務零侵入的方式解決微服務場景下面臨的分布式事務問題,它目前提供AT模式(即2PC)及TCC模式的分布式事務解決方案。

    3.1 設計思想

    Seata的設計目標包括了對業務的無侵入,因此從業務無侵入的2PC方案著手,在傳統的2PC的基礎上演進,并解決2PC方案面臨的問題。

    Seata把一個分布式事務理解成一個包含了若干個分支事務全局事務。全局事務的職責是協調其下管轄的分支事務達成一致,要么一起提交,要么一起失敗回滾。此外,通常分支事務本身就是一個關系數據庫的本地事務,下圖是全局事務與分支事務的關系圖:

    與傳統的2PC模型相比,Seata定義了三個組件來協調分布式事務的管理過程:

    • Transaction Coordinator(TC):事務協調器,它是獨立的中間件,需要獨立部署運行,它維護全局事務的運行狀態,接收TM指令發起全局事務的提交與回滾,負責與RM通信協調各個分支事務的提交或回滾;
    • Transaction Manager(TM):事務管理器,TM需要嵌入應用程序中工作,它負責開啟一個全局事務,并最終向TC發起全局提交或全局回滾的指令;
    • Resource Manager(RM):控制分支事務,負責分支注冊、狀態匯報,并接收事務協調器TC的指令,驅動分支(本地)事務的提交和回滾。

    3.2 執行流程

    依舊以新用戶注冊送積分舉例Seata的分布式事務過程:

    具體的執行流程如下:

  • 用戶服務的 TM 向 TC 申請開啟一個全局事務,全局事務創建成功并生成一個唯一的XID;
  • 用戶服務的 RM 向TC 注冊分支事務,該分支事務在用戶執行新增用戶邏輯,并將其納入 XID 對應全局事務的管轄;
  • 用戶服務執行分支事務,向用戶表插入一條記錄;
  • 邏輯執行到遠程調用積分服務時(XID在微服務調用鏈路的上下文傳播)。積分服務的RM向TC注冊分支事務,該分支事務執行增加積分的邏輯,并將其納入 XID 對應的全局事務的管轄;
  • 積分服務執行分支事務,向積分記錄表插入一條記錄,執行完畢,返回用戶服務;
  • 用戶服務分支事務執行完畢;
  • TM向TC發起針對XID的全局提交或回滾決議;
  • TC調度XID下管轄的全部分支事務完成提交或回滾請求。
  • 3.3 Seata的優勢

    架構層次方面,傳統2PC方案的RM實際上是在數據庫層,RM本質上就是數據庫本身,通過XA協議實現,而Seata的RM是以jar包的形式作為中間件層部署在應用程序這一側的。

    兩階段提交方面,傳統2PC無論第二階段的決是commit還是rollback,事務性資源的鎖都要保持到Phase2完成才能釋放,而Seata的做法是在Phase1就將本地事務提交,這樣就可以省去 Phase2 持鎖的時間,整體提高效率。

    3.4 二階段回滾

    二階段如果是提交的話就很容易理解,因為”業務SQL“在一階段已經提交至數據庫,所以Seata框架只需將一階段保存的快照數據和行鎖刪掉,完成數據清理即可。

    二階段如果是回滾的話,Seata就需要回滾一階段已經執行的”業務SQL“,還原業務數據。回滾方式便是用”before image“還原業務數據;但在還原前要首先校驗臟寫,對比”數據庫當前業務數據“和”after image“,如果兩份數據完全一致就說明沒有臟寫,可以還原業務數據,如果不一致就說明有臟寫,出現臟寫就需要轉人工處理。

    四、TCC事務補償

    TCC事務補償是基于2PC實現的業務層事務控制方案,TCC這一詞是由Try、Confirm和Cancel三個單詞的首字母,含義如下:

    • Try階段做業務檢查(一致性)及資源預留(隔離),此階段僅為一個初步操作,它和后續的Confirm一起才能真正構成一個完整的業務邏輯;
    • Confirm階段是做確認提交,Try階段所有分支事務執行成功后開始執行Confirm。通常情況下,采用TCC則認為Confirm階段是不會出錯的。即:只要Try成功,Confirm一定成功。若Confirm階段真的出錯了,需引入重試機制或人工處理;
    • Cancel階段是在業務執行錯誤需要回滾的狀態下執行分支事務的業務取消,預留資源釋放。通常情況下,采用TCC則認為Cancel階段也是一定會成功的。若Cancel階段真的出錯了,需引入重試機制或人工處理。

    TM首先發起所有的分支事務的Try操作,任何一個分支事務的Try操作執行失敗,TM將會發起所有分支事務的Cancel操作,若try操作全部成功,TM將會發起所有的分支事務的Confirm操作,其中Conrirm/Cancel操作若執行失敗,TM會進行那個重試。

    我們用一個下單同時減少庫存的業務來進行說明:

  • Try

    下單業務由訂單服務和庫存服務協同完成,在try階段訂單和庫存服務完成檢查和預留資源;

    訂單服務檢查當前是否滿足提交訂單的條件(比如:當前存在未完成的訂單,不允許提交新訂單);

    庫存服務檢查是否有充足的資源,并鎖定資源;

  • Confirm

    訂單服務和庫存服務完成Try后開始執行資源操作;

    訂單服務向訂單寫一條訂單信息;

    庫存服務減去庫存。

  • Cancel

    如果訂單服務和庫存服務有一方出現失敗則全部操作取消;

    訂單服務需要刪除新增的訂單信息。

    庫存服務將減去的庫存再還原。

  • 1. 空回滾

    在沒有調用TCC資源Try方法的情況下,調用了二階段的Cancel方法,Cancel方法需要識別出這是一個空回滾,然后直接返回成功。

    出現原因是當一個分支事務所在服務宕機或網絡異常,分支事務調用記錄為失敗,這個時候其實是沒有執行Try階段,當故障恢復后,分布式事務進行回滾則會調用二階段的Cancel方法,從而形成空回滾。

    解決思路的關鍵是要識別出這個空回滾。思路很簡單就是需要知道一階段是否執行了,如果執行了,那就是正常回滾;如果沒執行,那就是空回滾。前面已經說過TM在發起全局事務時生成全局事務記錄,全局事務ID貫穿整個分布式事務調用鏈。再額外增加一張分支事務記錄表,表中有全局事務ID貫穿和分支事務ID,第一階段Try方法里會插入一條記錄,表示一階段執行了。Cancel接口里讀取該記錄,如果該記錄存在,則正常回滾;如果該記錄不存在,則是空回滾。

    2. 冪等性

    TM(即事務管理器)在發起全局事務時生成全局事務記錄,全局事務ID貫穿整個分布式事務調用鏈條,用來記錄事務上下s文,追蹤和記錄狀態,由于Confirm和Cancel失敗需進行重試,因此需要實現為冪等。冪等性是指同一操作無論請求多少次,其結果都相同。

    所以為了保證TCC二階段提交重試機不會引發數據不一致,要求TCC的二階段Try、Confirm和Cancel接口保證冪等,這樣不會重復使用或者釋放資源。如果冪等控制沒做好,很有可能導致數據不一致等嚴重問題。

    3. 懸掛

    懸掛就是對于一個分布式事務,其二階段Cancel接口比Try接口先執行。

    出現原因是在RPC調用分支事務Try時,先注冊分支事務,再執行RPC調用,如果此時RPC調用的網絡發生擁堵,通常RPC調用是有超時時間的,RPC超時以后,TM就會通知RM回滾分布式事務,可能回滾完成后,RPC請求才到達參與者真正執行,而一個Try方法預留的業務資源,只有該分布式事務才能使用,該分布式事務第一階段預留的業務資源就再也沒有人能夠處理了,對于這種情況,我們稱之為懸掛,即業務資源預留后沒法繼續處理。

    解決思路是如果二階段執行完成,那一階段就不再繼續執行。在執行一階段事務時判斷在該全局事務下,”分支事務記錄“表中是否已有二階段事務記錄,如果有則不執行Try。

    五、可靠消息最終一致性

    可靠消息最終一致性方案是指當事務發起方執行完成本地事務后并發出一條消息,事務參與方(消息消費者)一定能夠接收消息并處理事務成功,此方案強調的是只要消息發給事務參與方最終事務要達到一致。

    此方案是利用消息中間件完成,如下圖:

    事務發起方(消息生成方)將消息發給消息中間件,事務參與方從消息中間件接收消息,事務發起方和消息中間件之間,事務參與方(消息消費方)和消息中間件之間都是通過網絡通信,由于網絡通信的不確定性會導致分布式事務問題。

    因此可靠消息最終一致性解決方案要解決以下幾個問題:

    1. 方案問題

    1.1 本地事務與消息發送的原子性問題

    本地事務與消息發送的原子性問題即:事務發起方在本地事務執行成功后消息必須發送出去,否則就丟棄消息。即實現本地消息和消息發送的原子性,要么都成功,要么都失敗。本地事務與消息發送的原子性問題是實現可靠消息最終一致性方案的關鍵問題。

    先來嘗試下這種操作,先發送消息,再操作數據庫:

    begin transaction:// 1. 發送MQ// 2. 數據庫操作 commit transaction;
    • 1
    • 2
    • 3
    • 4

    這種情況下無法保證數據庫操作與發送消息的一致性,因為可能發送消息成功,數據庫操作失敗。

    那么現在來看第二種方案,先進行數據庫操作,再發送消息:

    begin transaction:// 1. 數據庫操作// 2. 發送MQ commit transaction;
    • 1
    • 2
    • 3
    • 4

    這種情況下貌似沒有問題,如果發送MQ消息失敗,就會拋出異常,導致數據庫事務回滾。但如果是超時異常,數據庫回滾,但MQ其實已經正常發送了,同樣會導致不一致。

    1.2 事務參與方接收消息的可靠性

    事務參與方必須能夠從消息隊列接收到消息,如果接收消息失敗可以重復接收消息。

    1.3 消息重復消費的問題

    由于網絡2的存在,若某一消費節點超時但是消費成功,此時消息中間件會重復投遞此消息,就導致了消息的重復消費。

    要解決消息重復消費的問題就要實現事務參與方的方法冪等性。

    2. 解決方案

    2.1 本地消息表方案

    本地消息方案是通過本地事務保證數據業務操作和消息的一致性,然后通過定時任務將消息發送至消息中間件,待確認消息發送給消費方成功再將消息刪除。

    以注冊送積分為例來說明:

    一共有兩個微服務交互,用戶服務和積分服務,用戶服務負責添加用戶,積分服務負責添加積分:

    交互流程如下:

    2.1.1 用戶注冊

    用戶服務在本地事務新增用戶增加”積分消息日志“。(用戶表和消息表通過本地事務保證一致)

    下邊是偽代碼

    begin transaction;// 1. 新增用戶// 2. 存儲積分消息日志 commit transaction;
    • 1
    • 2
    • 3
    • 4

    這種情況下,本地數據庫操作與存儲積分消息日志處于同一事務中,本地數據庫操作與記錄消息日志操作具備原子性。

    2.1.2 定時任務掃描日志

    如何保證將消息發送給消息隊列呢?

    經過第一步消息已經寫到消息日志表中,可以啟動獨立的線程,定時對消息日志表中的消息進行掃描并發送至消息中間件,在消息中間件反饋成功后刪除該消息日志,否則等待定時任務下一周期重試。

    2.1.3 消費消息

    如何保證消費者一定能消費到消息呢?

    這里可以使用MQ的ACK(即消息確認)機制,消費者監聽MQ,如果消費者接受到消息并且業務處理完成后MQ發送ACK(即消息確認),此時說明消費者正常消費消息完成,MQ將不再向消費者推送消息,否則消費者會不斷重試向消費者來發送消息。

    積分服務接收到”增加積分“消息,開始增加積分,積分增加成功后向消息中間件回應ACK,否則消息中間件將重復投遞此消息。

    由于消息會重復投遞,積分服務的”增加積分“功能需要實現冪等性。

    2.2 RocketMQ事務消息方案

    RocketMQ是一個來自阿里巴巴的分布式消息中間件。RocketMQ事務消息設計則主要為了解決Producer端的消息發送與本地事務執行的原子性問題,RocketMQ設計中broker與producer端的雙向通信能力,使得broker天生可以作為一個事務協調者存在;而RocketMQ本身提供的存儲機制為事務消息提供了持久化能力;RocketMQ的高可用機制以及可靠消息設計則為事務消息在系統發生異常時依然能夠保證達成事務的最終一致性。

    在RocketMQ 4.3 后實現了完整的事務消息,實際上其實是對本地消息表的一個封裝,將本地消息表移動到了MQ內部,解決了 Producer 端的消息發送與本地事務執行的原子性問題。

    執行流程如下:

    我們還以注冊送積分的例子來描述整個流程。

    Producer即MQ發送方,本例中是用戶服務,負責新增用戶。MQ訂閱方即消息消費方,本例中是積分服務,負責新增積分。

  • Producer發送事務消息

    Producer(MQ發送方)發送事務消息至MQ Server,MQ Server將消息狀態標記為 Prepared(預備狀態),注意此時這條消息消費者(MQ訂閱方)是無法消費到的。

    本例中,Producer發送”增加積分消息“到 MQ Server。

  • MQ Server回應消息發送成功

    MQ Server接收到Producer發送給的消息則回應發送表示MQ已接受到消息。

  • Producer執行本地事務

    Producer端執行業務代碼邏輯,通過本地數據庫事務控制。本例中,Producer執行添加用戶操作。

  • 消息投遞

    若Producer本地事務執行成功功則自動向MQServer發送commit消息,MQ Server接收到commit消息后將”增加積 分消息“ 狀態標記為可消費,此時MQ訂閱方(積分服務)即正常消費消息;

    若Producer 本地事務執行失敗則自動向MQServer發送rollback消息,MQ Server接收到rollback消息后 將刪 除”增加積分消息“ 。

    MQ訂閱方(積分服務)消費消息,消費成功則向MQ回應ack,否則將重復接收消息。這里ack默認自動回應,即 程序執行正常則自動回應ack。

  • 事務回查

    如果執行Producer端本地事務過程中,執行端掛掉,或者超時,MQ Server將會不停的詢問同組的其他 Producer 來獲取事務執行狀態,這個過程叫事務回查。MQ Server會根據事務回查結果來決定是否投遞消息。

    以上主干流程已由RocketMQ實現,對用戶側來說,用戶需要分別實現本地事務執行以及本地事務回查方法,因此 只需關注本地事務的執行狀態即可。

    RoacketMQ提供RocketMQQLocalTransactionListener接口:

    public interface RocketMQLocalTransactionListener {/** ‐ 發送prepare消息成功此方法被回調,該方法用于執行本地事務 ‐ @param msg 回傳的消息,利用transactionId即可獲取到該消息的唯一Id ‐ @param arg 調用send方法時傳遞的參數,當send時候若有額外的參數可以傳遞到send方法中,這里能獲取到 ‐ @return 返回事務狀態,COMMIT:提交 ROLLBACK:回滾 UNKNOW:回調 */RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg); /** ‐ @param msg 通過獲取transactionId來判斷這條消息的本地事務執行狀態 ‐ @return 返回事務狀態,COMMIT:提交 ROLLBACK:回滾 UNKNOW:回調 */ RocketMQLocalTransactionState checkLocalTransaction(Message msg); }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    發送事務消息:以下是RocketMQ提供用于發送事務消息的API:

    TransactionMQProducer producer = new TransactionMQProducer("ProducerGroup"); producer.setNamesrvAddr("127.0.0.1:9876"); producer.start(); // 設置TransactionListener實現 producer.setTransactionListener(transactionListener); // 發送事務消息 SendResult sendResult = producer.sendMessageInTransaction(msg, null);
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  • 六、最大努力通知

    1. 最大努力通知介紹

    最大努力通知也是一種解決分布式事務的方案,下面以一個充值的案例舉例:

    交互流程:

  • 賬戶系統調用充值系統接口

  • 充值系統完成支付處理向賬戶系統發起充值結果通知若通知失敗,則充值系統按策略進行重復通知

  • 賬戶系統接收到充值結果通知修改充值狀態。

  • 賬戶系統未接收到通知會主動調用充值系統的接口查詢充值結果。

  • 通過上邊的例子我們總結最大努力通知方案的目標:

    目標:發起通知方通過一定的機制最大努力將業務處理結果通知到接收方。

    具體包括:

  • 有一定的消息重復通知機制

    因為接收通知方可能沒有接收到通知,此時要有一定的機制對消息重復通知;

  • 消息校對機制

    如果盡最大努力也沒有通知到接收方,或者接收方消費消息后要再次消費,此時可由接收方主動向通知方查詢消息來滿足需求。

  • 最大努力通知與可靠消息一致性有什么不同?

  • 解決方案思想不同

    可靠消息一致性,發起通知方需要保證將消息發出去,并且將消息發到接收通知方,消息的可靠性關鍵由發起通知 方來保證。

    最大努力通知,發起通知方盡最大的努力將業務處理結果通知為接收通知方,但是可能消息接收不到,此時需要接收通知方主動調用發起通知方的接口查詢業務處理結果,通知的可靠性關鍵在接收通知方。

  • 兩者的業務應用場景不同

    可靠消息一致性關注的是交易過程的事務一致,以異步的方式完成交易。

    最大努力通知關注的是交易后的通知事務,即將交易結果可靠的通知出去。

  • 技術解決方向不同

    可靠消息一致性要解決消息從發出到接收的一致性,即消息發出并且被接收到。

    最大努力通知無法保證消息從發出到接收的一致性,只提供消息接收的可靠性機制。可靠機制是,最大努力的將消 息通知給接收方,當消息無法被接收方接收時,由接收方主動查詢消息(業務處理結果)。

  • 2. 解決方案

    通過對最大努力通知的理解,采用MQ的ack機制就可以實現最大努力通知。

    方案1:

    本方案是利用MQ的ack機制由MQ向接收通知方發送通知,流程如下:

  • 發起通知方將通知發給MQ。
  • 使用普通消息機制將通知發給MQ。

    注意:如果消息沒有發出去可由接收通知方主動請求發起通知方查詢業務執行結果。(后邊會講)

  • 接收通知方監聽 MQ。

  • 接收通知方接收消息,業務處理完成回應ack。

  • 接收通知方若沒有回應ack則MQ會重復通知。

  • MQ會按照間隔1 min、5 min、10 min、30 min、1 h、2 h、5 h、10 h的方式,逐步拉大通知間隔(如果 MQ 采用rocketMQ,在broker中可進行配置),直到達到通知要求的時間窗口上限。

    5、接收通知方可通過消息校對接口來校對消息的一致性。

    方案2:

    本方案也是利用MQ的ack機制,與方案1不同的是應用程序向接收通知方發送通知,如下圖:

    交互流程如下:

  • 發起通知方將通知發給MQ。

    使用可靠消息一致方案中的事務消息保證本地事務與消息的原子性,最終將通知先發給MQ。

  • 通知程序監聽 MQ,接收MQ的消息。

    方案1中接收通知方直接監聽MQ,方案2中由通知程序監聽MQ。通知程序若沒有回應ack則MQ會重復通知。

  • 通知程序通過互聯網接口協議(如http、webservice)調用接收通知方案接口,完成通知。

    通知程序調用接收通知方案接口成功就表示通知成功,即消費MQ消息成功,MQ將不再向通知程序投遞通知消 息。

  • 接收通知方可通過消息校對接口來校對消息的一致性。

  • 方案1和方案2的不同點:

  • 方案1中接收通知方與MQ接口,即接收通知方案監聽 MQ,此方案主要應用與內部應用之間的通知。

  • 方案2中由通知程序與MQ接口,通知程序監聽MQ,收到MQ的消息后由通知程序通過互聯網接口協議調用接收 通知方。此方案主要應用于外部應用之間的通知,例如支付寶、微信的支付結果通知。

  • 資料收集于網絡。

    總結

    以上是生活随笔為你收集整理的【转】分布式事务的常见解决方案的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。