RocketMQ事務消息實現分佈式事務

一、前言

分佈式事務詳解:https://hucheng.blog.csdn.net/article/details/102975855

分佈式事務,我們一般都是強調的最終一致性,而不是強一致性。

RocketMQ分佈式事務執行流程圖:
在這裏插入圖片描述

RocketMQ事務消息中概念

Half(Prepare) Message

指的是暫不能投遞的消息,發送方已經將消息成功發送到了 MQ 服務端,但是服務端未收到生產者對該消息的二次確認,此時該消息被標記成“暫不能投遞”狀態,處於該種狀態下的消息即半消息。

消息回查

由於網絡閃斷、生產者應用重啓等原因,導致某條事務消息的二次確認丟失,MQ 服務端通過掃描發現某條消息長期處於“半消息”時,需要主動向消息生產者詢問該消息的最終狀態(Commit 或是 Rollback),該過程即消息回查。

事務消息狀態

  • TransactionStatus.CommitTransaction:提交事務,它允許消費者消費消息。
  • TransactionStatus.RollbackTransaction:回滾事務,它代表消息將被刪除,不允許被消費。
  • TransactionStatus.Unknown:中間狀態,它代表需要檢查消息隊列來確認狀態。

二 、RoctetMQ事務消息實現分佈式事務

我們舉一個扣款的例子,在單體項目中,我們很容易的去控制以下流程的事務:
在這裏插入圖片描述
而後面變成分佈式架構後,數據庫也可能分庫分表,此時我們控制分佈式事務很大,那麼豈不是單體應用的響應速度大於分佈式系統?
在這裏插入圖片描述
這裏我們可以將大事務轉換爲本地事務+異步消息
在這裏插入圖片描述
這裏會存在一個問題,如何保證本地事務和異步消息的同時執行或者回滾?

RocketMQ事務消息即可保證這點:

事務消息producer的設置:

producer.setTransactionListener(new TransactionListener() {
	/**
	 * 在該方法中執行本地事務
	 */
	@Override
	public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
		String tag = msg.getTags();
		//本地事務執行
		if (StringUtils.equals("TransactionA", msg.getTags())) {
			try{
				//執行本地業務代碼
			}catch(Exception e){
				//本地業務代碼異常,則也不發送消息
				return LocalTransactionState.COMMIT_MESSAGE;
			}
			
		} 
		return LocalTransactionState.COMMIT_MESSAGE;
	}

	/**
	 * 對狀態爲LocalTransactionState.UNKNOW會進行回查
	 */
	@Override
	public LocalTransactionState checkLocalTransaction(MessageExt msg) {
		//這裏進行回查處理
		return LocalTransactionState.COMMIT_MESSAGE;
	}
});

 //發送事務消息
SendResult result = producer.sendMessageInTransaction(msg, null);

三 、RoctetMQ事務消息的限制

  1. 事務消息不支持延時消息和批量消息
  2. 爲了避免單個消息被檢查太多次而導致半隊列消息累積,我們默認將單個消息的檢查次數限制爲15次,但是用戶可以通過Broker配置文件的transactionCheckMax參數來修改此限制。如果已經檢查某條消息超過N次的話( N= transactioncheckmax)則Broker將丟棄此消息,並在默認情況下同時打印錯誤日誌。用戶可以通過重寫AbstractTransactionCheckListener類來修改這個行爲。
  3. 事務消息將在Broker配置文件中的參數transactionMsgTimeout這樣的特定時間長度之後被檢查。當發送事務消息時,用戶還可以通過設置用戶屬性CHECK_IMMUNITY_TIME_IN_SECONDS來改變這個限制,該參數優先於transactionMsgTimeout參數。
  4. 事務性消息可能不止一次被檢查或消費。
  5. 提交給用戶的目標主題消息可能會失敗,目前這依日誌的記錄而定。它的高可用性通過RocketMQ本身的高可用性機制來保證,如果希望確保事務消息不丟失、並且事務完整性得到保證,建議使用同步的雙重寫入機制。
  6. 事務消息的生產者ID不能與其他類型消息的生產者ID共享。與其他類型的消息不同,事務消息允許反向查詢、MQ服務器能通過它們的生產者ID查詢到消費者。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章