分佈式事務解決方案—事務消息
普通消息難以保證生產者的事務操作與消息發送的原子性,所以可能會導致數據不一致;RocketMQ 提供了一種在普通消息基礎上支持二階段的提交能力事務消息,事務消息可以支持在分佈式場景下保障消息生產和本地事務的最終一致性。
1、事務消息基本概念
(1)半消息
生產者發送的消息首先作爲 “半消息” 存儲在 Broker 中,對消費者不可見。Broker 等待生產者確認消息狀態(提交或回滾),事務消息有 3 種狀態如下所示:
(2)事務狀態檢查
如果生產者未及時確認,Broker 會定時回查生產者的事務的最終狀態,通過回查的最終狀態決定半消息是提交還是回滾操作。
(3)接口 API
RocketMQ 提供了兩大重要的接口,分別是 TransactionMQProducer 和 TransactionListener,這個兩個接口主要用於發送事務消息並處理本地事務邏輯。
(4)存儲與可靠性
事務消息存儲在 Broker 的專門的隊列中,通過記錄事務狀態日誌來確保高可用性和一致性。相對於普通消息,事務消息增加了半消息階段和狀態檢查機制,然後通過狀態檢查機制來保證分佈式下數據的最終一致性。
2、事務消息的實現
RocketMQ 事務消息的實現原理圖如下所示:
第一階段:
A 服務中生產者發送半消息至 RocketMQ 的服務端,RocketMQ 服務端將消息持久化後,向生產者返回 ACK 確認消息,表示消息已經發送成功,此時消息會持久化在 RocketMQ 的隊列中,這個消息對於消費者暫不能消費。
A 服務執行本地的業務邏輯,然後根據 A 服務本地事務執行結果確定第二階段的提交 / 回滾操作。
第二階段:
(1)A 服務的本地事務執行成功,此時消息的確認結果爲提交,那麼 RocketMQ 服務端將半消息事務標記爲可消費的完整消息,如下圖所示:
消息變成完整消息後就可以被消費者消費了。
(2)A 服務的本地事務執行失敗,此時消息的確認結果爲回滾,那麼 RocketMQ 將半事務消息刪除,這樣就不會投遞給消費者消費。
(3)爲了保證第二階段的數據一致性,RocketMQ 提供了針對半消息的消息狀態回查機制,即就是如果 RocketMQ 服務端未收到生產者提交的二次確認結果或者收到的確認結果爲未知狀態 (Unknow),RocketMQ 服務端會定期對消息生產者發起回查機制。
當 A 服務接收到回查任務的時候,會檢查本地事務執行的最終結果,然後提交事務執行的最終結果給 RocketMQ 服務端,RocketMQ 服務端根據最終的執行結果決定這個半消息是提交還是回滾。
總結:
(1)RocketMQ 的事務消息保證了本地事務與事務消息發送的一致性,本地事務執行成功,事務消息方可投遞到消費者端處理。
(2)未收到生產者提交的二次確認結果或者收到的確認結果爲未知狀態的半消息,RocketMQ 提供了消息狀態回查機制,通過回查生產者端的本地事務的執行結果來判斷半消息的最終狀態。
(3)RocketMQ 事務消息提供了超時機制,即半事務消息被生產者發送到 Broker 後,如果在指定時間內(默認 4 小時)服務端無法確認提交或者回滾狀態,則消息默認會被回滾。
(4)RocketMQ 事務消息無法實現嚴格的實時一致性,只能保證最終一致性,所以針對那些實時性要求高的場景下 RocketMQ 事務消息是不適合的。
(5)事務執行時間過長會影響系統整體吞吐量,同時在消費者端需要消費者自行的實現消息的冪等處理。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/t7Rdix-eD1uzFIm43xRmeg