假設(shè):消息服務(wù)不丟消息
場景 服務(wù)A 服務(wù)B 服務(wù)C 消息服務(wù)Q
偽代碼
服務(wù)A中
transaction{
A本地事務(wù)
B.callB();
C.callC();
A本地事務(wù)
}
利用消息服務(wù)來實現(xiàn)分布式事務(wù)
原理 當(dāng)服務(wù)A執(zhí)行事務(wù)時,所有指定遠(yuǎn)程調(diào)用會被轉(zhuǎn)換為發(fā)送一條調(diào)用消息到消息服務(wù),當(dāng)B和C接收到消息時,立即執(zhí)行消息指定的方法偏瓤,并在提交前發(fā)送回復(fù)消息給A(攜帶有返回值)并且等待接收提交或者回滾消息,服務(wù)A執(zhí)行完方法也在提交前等待B和C的回復(fù)布朦,當(dāng)B和C的回復(fù)都為sucess時發(fā)送提交消息給B和C,然后自己提交肆饶,否則回滾骆捧。B和C接到提交消息后,提交顿膨,否則回滾锅锨。
異常情況一:在發(fā)送調(diào)用B的消息時失敗
服務(wù)A事務(wù)直接回滾
異常情況二:在發(fā)送調(diào)用C的消息時失敗
服務(wù)A事務(wù)直接回滾,并發(fā)送回滾消息到指定隊列(此兩步操作由Q的事務(wù)消息保證原子性)
異常情況三:服務(wù)A提交和回滾失敗
由于服務(wù)A提交和回滾操作和發(fā)送提交或者回滾消息在一個事務(wù)內(nèi)恋沃,所以放在一起討論必搞,
由于此部分由消息中間件保證原子性,固提交或者回滾失敗芽唇,不會有提交或者回滾消息到達(dá)消息中間件,B和C等待一段時間后自動回滾
異常情況四:B在發(fā)送回復(fù)消息時失敗
A在等待指定時間后沒有收到B的回復(fù),進(jìn)行回滾操作并發(fā)送回滾消息到指定隊列匆笤,C在收到回滾消息后回滾研侣,B在等待指定時間后沒有收到A的提交消息回滾
異常情況五:C在發(fā)送回復(fù)消息時失敗
同異常情況四
異常情況六:B提交失敗或者C提交失敗
B或C中調(diào)用消息和提交消息均不消費,會進(jìn)行重試
異常情況七:B或者C回滾失敗
同異常情況六
異常情況八:B或者C邏輯出現(xiàn)異常導(dǎo)致失敗
B或者C直接回滾炮捧,并且發(fā)送失敗回復(fù)
停機啟動恢復(fù)處理
由于異常導(dǎo)致的死機庶诡,然后重啟后的邏輯
一、只接收到調(diào)用消息咆课,執(zhí)行末誓,然后等待固定時間后回滾。
二书蚪、按照順序接收到調(diào)用消息和提交消息喇澡,執(zhí)行然后提交
三、先接收到提交消息后接收到調(diào)用消息殊校,一樣晴玖,執(zhí)行然后提交
四、接收到調(diào)用和回滾消息为流,同上
從上可以推導(dǎo)出呕屎,利用消息系統(tǒng)做分布式事務(wù)的兩個特性
強調(diào)一下假設(shè):消息服務(wù)不丟消息
一、在網(wǎng)絡(luò)暢通所有服務(wù)高可用的情況下敬察,可以做到數(shù)據(jù)的強一致性
二秀睛、在網(wǎng)絡(luò)和服務(wù)可能存在故障的情況下,可以做到數(shù)據(jù)的最終一致性
關(guān)于數(shù)據(jù)在最終一致性情況下的查詢問題
1.最好的解決方案是不管莲祸,更新后查詢數(shù)據(jù)查到舊的數(shù)據(jù)就讓它查到舊的數(shù)據(jù)
2.可以利用緩存蹂安,自己寫邏輯實現(xiàn),還未提交的數(shù)據(jù)緩存下來虫给,查詢時先查詢緩存