消息隊列解決分佈式事務

消息隊列解決分佈式事務

  1. 本地消息表:通常處於同一張數據表,通過事務觸發器就能實現,但無法解決兩張表處於不同的數據庫問題

    begin transaction:
    update User set account = account - 100 where userId = 'A'
    insert into message(userId,amount,status) values('A',100,1)
    commit transaction
    
  2. 分佈式事務-兩階段提交消息:

    • 基本原理:通過TC事務協調器,分別去確認A,B,C事務的發生,全部成功則使用TC進行提交,否則的話則進行abort

    • 缺點:涉及多次節點提交,通信時間太長;鎖定的資源也變得更多。

      2.prepare
      2.prepare
      1.start
      3.yes
      3.yes
      4.commit
      4.commit
      TC事務觸發器
      A
      B
      Client
  3. 分佈式事務 - 業務方自己實現(使用消息隊列來避免分佈式事務),例子:B事務伴隨着A事務的發生

    • 基本原理:將創建事務和發佈事務分成兩步操作,創建事務A會在本地數據庫存入消息數據庫M進行記錄,而並不發送消息至B;

      當A事務完成時,再將M發送至B;

      B中通過M_Apply表查找這一消息是否已經操作,未操作則觸發操作,或者拋棄;

      B事務完成後,將消息發送至A,A再在庫裏面刪除M表;

      即需要存在的表有:要執行的A表和B表,M表(存儲A的事務消息發起,存在於A數據庫)和M_apply(校驗M消息,存在於B數據庫)

      //表M的存在是實現業務與消息的耦合與解耦
      begin transaction
      update A
      set amout=amount - 1000
      where userid=1
      insert into message(userid,amount,status) values (1,1000,1)
      end transaction
      commit;
      //表M_apply的存在解決消息的重複提交
      for each msg in queue
      begin transaction 
      select count(*) as cnf from message_apply where msg_id=msg.msg_id;
      if cnt==0 then
      update B
      set amount = amount + 10000;
      where userId =1;
      insert into mssage_apply(msg_id) values (msg.msg_id);
      //如果應用則將m中數據的id插入mssage_apply
      end transaction1
      commit
      

      缺點:需要設計DB消息表,同時還需要一個後臺任務,不斷掃描本地消息。導致消息的處理和業務邏輯耦合額外增加業務方的負擔。

  4. 分佈式事務 - RocketMQ 事務消息

    • 基本原理:
      1. 事務發起方首先發送 prepare 消息到 MQ。
      2. 在發送 prepare 消息成功後執行本地事務。
      3. 根據本地事務執行結果返回 commit 或者是 rollback。
      4. 如果消息是 rollback,MQ 將刪除該 prepare 消息不進行下發,如果是 commit 消息,MQ 將會把這個消息發送給 consumer 端。
      5. 如果執行本地事務過程中,執行端掛掉,或者超時,MQ 將會不停的詢問其同組的其他 producer 來獲取狀態。
      6. Consumer 端的消費成功機制有 MQ 保證
  5. 如果事務消息不能夠解決以上存在的問題,比如發送端發送成功但接受端一直失敗,此時狀態下,應當使用人工介入進行回滾。但回滾代價巨大,應儘量避免。

  6. 目前較多的分佈式事務解決方案:

    • 結合MQ消息中間件實現可靠傳輸(目前電商最爲流行的方式)

    • TCC補償性事務解決方案

    • 最大努力通知型方案

      ​ 第一種方案:可靠消息最終一致性,需要業務系統結合MQ消息中間件實現,在實現過程中需要保證消息的成功發送及成功消費。即需要通過業務系統控制MQ的消息狀態
      ​ 第二種方案:TCC補償性,分爲三個階段TRYING-CONFIRMING-CANCELING。每個階段做不同的處理.

      ​ TRYING階段主要是對業務系統進行檢測及資源預留
      ​ CONFIRMING階段是做業務提交,通過TRYING階段執行成功後,再執行該階段。默認如果TRYING階段執行成功,CONFIRMING就一定能成功。
      ​ CANCELING階段是回對業務做回滾,在TRYING階段中,如果存在分支事務TRYING失敗,則需要調用CANCELING將已預留的資源進行釋放。
      ​ 第三種方案:最大努力通知xing型,這種方案主要用在與第三方系統通訊時,比如:調用微信或支付寶支付後的支付結果通知。這種方案也是結合MQ進行實現,例如:通過MQ發送http請求,設置最大通知次數。達到通知次數後即不再通知。

  7. 主流的開源MQ(ActiveMQ、RabbitMQ、Kafka、redis)RocketMQ(alibaba)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章