消息隊列解決分布式事務
- 本地消息表:通常處于同一張資料表,通過事務觸發器就能實作,但無法解決兩張表處于不同的資料庫問題
begin transaction: update User set account = account - 100 where userId = 'A' insert into message(userId,amount,status) values('A',100,1) commit transaction
- 分布式事務-兩階段送出消息:
- 基本原理:通過TC事務協調器,分别去确認A,B,C事務的發生,全部成功則使用TC進行送出,否則的話則進行abort
- 缺點:涉及多次節點送出,通信時間太長;鎖定的資源也變得更多。
- 分布式事務 - 業務方自己實作(使用消息隊列來避免分布式事務),例子:B事務伴随着A事務的發生
-
基本原理:将建立事務和釋出事務分成兩步操作,建立事務A會在本地資料庫存入消息資料庫M進行記錄,而并不發送消息至B;
當A事務完成時,再将M發送至B;
B中通過M_Apply表查找這一消息是否已經操作,未操作則觸發操作,或者抛棄;
B事務完成後,将消息發送至A,A再在庫裡面删除M表;
即需要存在的表有:要執行的A表和B表,M表(存儲A的事務消息發起,存在于A資料庫)和M_apply(校驗M消息,存在于B資料庫)
缺點:需要設計DB消息表,同時還需要一個背景任務,不斷掃描本地消息。導緻消息的處理和業務邏輯耦合額外增加業務方的負擔。//表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
-
- 分布式事務 - RocketMQ 事務消息
- 基本原理:
- 事務發起方首先發送 prepare 消息到 MQ。
- 在發送 prepare 消息成功後執行本地事務。
- 根據本地事務執行結果傳回 commit 或者是 rollback。
- 如果消息是 rollback,MQ 将删除該 prepare 消息不進行下發,如果是 commit 消息,MQ 将會把這個消息發送給 consumer 端。
- 如果執行本地事務過程中,執行端挂掉,或者逾時,MQ 将會不停的詢問其同組的其他 producer 來擷取狀态。
- Consumer 端的消費成功機制有 MQ 保證
- 基本原理:
- 如果事務消息不能夠解決以上存在的問題,比如發送端發送成功但接受端一直失敗,此時狀态下,應當使用人工介入進行復原。但復原代價巨大,應盡量避免。
- 目前較多的分布式事務解決方案:
- 結合MQ消息中間件實作可靠傳輸(目前電商最為流行的方式)
- TCC補償性事務解決方案
-
最大努力通知型方案
第一種方案:可靠消息最終一緻性,需要業務系統結合MQ消息中間件實作,在實作過程中需要保證消息的成功發送及成功消費。即需要通過業務系統控制MQ的消息狀态
第二種方案:TCC補償性,分為三個階段TRYING-CONFIRMING-CANCELING。每個階段做不同的處理.
TRYING階段主要是對業務系統進行檢測及資源預留
CONFIRMING階段是做業務送出,通過TRYING階段執行成功後,再執行該階段。預設如果TRYING階段執行成功,CONFIRMING就一定能成功。
CANCELING階段是回對業務做復原,在TRYING階段中,如果存在分支事務TRYING失敗,則需要調用CANCELING将已預留的資源進行釋放。
第三種方案:最大努力通知xing型,這種方案主要用在與第三方系統通訊時,比如:調用微信或支付寶支付後的支付結果通知。這種方案也是結合MQ進行實作,例如:通過MQ發送http請求,設定最大通知次數。達到通知次數後即不再通知。
- 主流的開源MQ(ActiveMQ、RabbitMQ、Kafka、redis)RocketMQ(alibaba)