分布式事務解決方案—事務消息
普通消息難以保證生產(chǎn)者的事務操作與消息發(fā)送的原子性,所以可能會導致數(shù)據(jù)不一致;RocketMQ提供了一種在普通消息基礎上支持二階段的提交能力事務消息,事務消息可以支持在分布式場景下保障消息生產(chǎn)和本地事務的最終一致性。
1、事務消息基本概念
(1)半消息
生產(chǎn)者發(fā)送的消息首先作為“半消息”存儲在Broker中,對消費者不可見。Broker 等待生產(chǎn)者確認消息狀態(tài)(提交或回滾),事務消息有3種狀態(tài)如下所示:
狀態(tài) | 狀態(tài)的描述 |
TransactionStatus.CommitTransaction | 提交事務,表示允許消費者消費(使用)這條消息 |
TransactionStatus.RollbackTransaction | 回滾事務,表示消息將被刪除,不允許使用 |
TransactionStatus.Unknown | 中間狀態(tài),表示需要MQ向消息發(fā)送方進行檢查以確定狀態(tài) |
(2)事務狀態(tài)檢查
如果生產(chǎn)者未及時確認,Broker會定時回查生產(chǎn)者的事務的最終狀態(tài),通過回查的最終狀態(tài)決定半消息是提交還是回滾操作。
(3)接口API
RocketMQ提供了兩大重要的接口,分別是TransactionMQProducer 和TransactionListener,這個兩個接口主要用于發(fā)送事務消息并處理本地事務邏輯。
(4)存儲與可靠性
事務消息存儲在Broker的專門的隊列中,通過記錄事務狀態(tài)日志來確保高可用性和一致性。相對于普通消息,事務消息增加了半消息階段和狀態(tài)檢查機制,然后通過狀態(tài)檢查機制來保證分布式下數(shù)據(jù)的最終一致性。
2、事務消息的實現(xiàn)
RocketMQ事務消息的實現(xiàn)原理圖如下所示:
圖片
第一階段
A服務中生產(chǎn)者發(fā)送半消息至RocketMQ的服務端,RocketMQ服務端將消息持久化后,向生產(chǎn)者返回ACK確認消息,表示消息已經(jīng)發(fā)送成功,此時消息會持久化在RocketMQ的隊列中,這個消息對于消費者暫不能消費。
A服務執(zhí)行本地的業(yè)務邏輯,然后根據(jù)A服務本地事務執(zhí)行結(jié)果確定第二階段的提交/回滾操作。
第二階段
(1)A服務的本地事務執(zhí)行成功,此時消息的確認結(jié)果為提交,那么RocketMQ服務端將半消息事務標記為可消費的完整消息,如下圖所示:
圖片
消息變成完整消息后就可以被消費者消費了。
(2)A服務的本地事務執(zhí)行失敗,此時消息的確認結(jié)果為回滾,那么RocketMQ將半事務消息刪除,這樣就不會投遞給消費者消費。
(3)為了保證第二階段的數(shù)據(jù)一致性,RocketMQ提供了針對半消息的消息狀態(tài)回查機制,即就是如果RocketMQ服務端未收到生產(chǎn)者提交的二次確認結(jié)果或者收到的確認結(jié)果為未知狀態(tài)(Unknow),RocketMQ服務端會定期對消息生產(chǎn)者發(fā)起回查機制。
當A服務接收到回查任務的時候,會檢查本地事務執(zhí)行的最終結(jié)果,然后提交事務執(zhí)行的最終結(jié)果給RocketMQ服務端,RocketMQ服務端根據(jù)最終的執(zhí)行結(jié)果決定這個半消息是提交還是回滾。
總結(jié)
(1)RocketMQ的事務消息保證了本地事務與事務消息發(fā)送的一致性,本地事務執(zhí)行成功,事務消息方可投遞到消費者端處理。
(2)未收到生產(chǎn)者提交的二次確認結(jié)果或者收到的確認結(jié)果為未知狀態(tài)的半消息,RocketMQ提供了消息狀態(tài)回查機制,通過回查生產(chǎn)者端的本地事務的執(zhí)行結(jié)果來判斷半消息的最終狀態(tài)。
(3)RocketMQ事務消息提供了超時機制,即半事務消息被生產(chǎn)者發(fā)送到Broker后,如果在指定時間內(nèi)(默認4小時)服務端無法確認提交或者回滾狀態(tài),則消息默認會被回滾。
(4)RocketMQ事務消息無法實現(xiàn)嚴格的實時一致性,只能保證最終一致性,所以針對那些實時性要求高的場景下RocketMQ事務消息是不適合的。
(5)事務執(zhí)行時間過長會影響系統(tǒng)整體吞吐量,同時在消費者端需要消費者自行的實現(xiàn)消息的冪等處理。