先丟擲問題
老生常談的問題:就是a,b在不同的伺服器,然後a賬戶減錢,b賬戶加錢。因為他們不在同乙個事務下,所以,就會出現a減錢,b加錢沒成,然後就導致資料不完整。
那麼rocketmq是如何解決這問題呢
採用:最終一致性
核心思路就是【狀態回查】,也就是rocketmq會定時遍歷commitlog中的預備訊息。
因為預備訊息最終肯定會變為commit訊息或rollback訊息,所以遍歷預備訊息去回查本地業務的執行狀態,如果發現本地業務沒有執行成功就rollback,如果執行成功就傳送commit訊息。
這裡我們先改造defaultproductconfig類
@component
public
class
defaultproductconfig")
private string producergroup;
@value
("$"
)private string nameserver;
//我們用帶事務的生產者,並且,這裡把生產者的事務***註冊進來producertxmsglistener
@bean
public transactionmqproducer getproduct()
throws mqclientexception
}
事務***:producertxmsglistener
@component
public
class
producertxmsglistener
implements
transactionlistener
", jsonstring)
;return localtransactionstate.unknow;
}catch
(exception e)
}//這裡是如果上面方法返回的是未知,就開始執行這個方法,做本地檢查,並最終判斷這個提交訊息,是需要傳送成功,還是回滾
@override
public localtransactionstate checklocaltransaction
(messageext msg)
", jsonstring);if
(jsonstring != null)
else
return state;
}
然後是傳送訊息工具類:sendmsgutil
@component
public
class
sendmsgutil")
private string topic;
@autowired
transactionmqproducer defaultmqproducer;
public sendresult sendmsg
(order order, msgproductbean object)
, 儲存queue={}, 訂單order={} , 訂單狀態status={}", sendresult.getsendstatus(),
// sendresult.getmessagequeue().getqueueid(), order.getorderno(), order.getorderstatus());
//這裡返回的狀態不代表訊息是否傳送成功
transactionsendresult sendresult = defaultmqproducer.
sendmessageintransaction
(message, null)
; logger.
info
("返回狀態:"
+ sendresult.
getsendstatus()
);return null;
}catch
(mqclientexception e)
return null;
}
消費端**不變,我們進行測試,我們預提交,先返回未知狀態,然後在回查事務的時候,返回狀態是提交,然後看消費端消費訊息的時機
可以看到消費端沒有收到任務結果:
當我們回查事務成功時:
生產端:
那b服務失敗怎麼辦?
如果b最終執行失敗,幾乎可以斷定就是**有問題所以才引起的異常,因為消費端rocketmq有重試機制,如果不是**問題一般重試幾次就能成功。如果是**的原因引起多次重試失敗後,也沒有關係,將該異常記錄下來,由人工處理,人工兜底處理後,就可以讓事務達到最終的一致性。
基於RocketMQ的分布式事務
最近看到一篇分布式事務解決方案文章 柔性事務,要求最終一致性,允許中間狀態短期不一致。相對于強一致性事務 剛性事務 而言,它鎖定的資源範圍小,阻塞性弱,更為高效。柔性事務有多種實現方式,包括tcc saga 事務訊息 最大努力通知等,本文將重點介紹通過事務訊息實現柔性事務。以下為部分正文 針對搶購類...
分布式 分布式事務
是資料庫執行過程中的乙個邏輯單位,由乙個有限的資料庫操作序列構成。事務的acid四大特性 原子性 atomicity 事務作為乙個整體被執行。一致性 consistency 從乙個一致的狀態轉換到另乙個一致的狀態。隔離性 isolation 多個事務併發執行時,併發事務之間互相影響的程度。永續性 d...
分布式事務 分布式事務的實現
如果在多個服務中需要對不同的資料庫進行操作。因為不同服務操作的資料庫都不同,所以保證在同乙個事務中完成操作顯然是不科學的。那實現分布式事務的思想 1 方法入口,建立一條日誌記錄,狀態定義為初始狀態,即儲存本條日誌記錄 可以儲存在資料庫中,也可以寫出到本地磁碟檔案 2 可以在非同步執行緒或在定時任務中...