方法一喷市、補償事務(wù)(TCC)? 嚴選跌宛、阿里酗宋、螞蟻金服
Tcc 其實就是采用的補償機制,其核心思想是:針對每個操作疆拘,都要注冊一個與其對應(yīng)的確認和補償(撤銷)操作蜕猫,它分為三個階段
try階段:主要是對業(yè)務(wù)系統(tǒng)做檢測及預(yù)留資源
confirm階段:主要是對業(yè)務(wù)系統(tǒng)做確認提交,try階段執(zhí)行成功并開始執(zhí)行confirm階段時哎迄,默認-- confirm階段是不會錯誤的回右,即只要try成功,confirm一定成功
cancel階段:主要是在業(yè)務(wù)執(zhí)行錯誤漱挚,需要回滾的狀態(tài)下執(zhí)行的業(yè)務(wù)取消翔烁,預(yù)留資源釋放
? 舉例說明
張三要向李四轉(zhuǎn)賬,思路大概是:我們有一個本地方法旨涝,里面依次調(diào)用
? ①. 首先在try階段租漂,要先調(diào)用遠程接口把兩個人的錢凍結(jié)起
? ②. 在confirm階段,執(zhí)行遠程調(diào)用的轉(zhuǎn)賬的操作颊糜,轉(zhuǎn)賬成功進行解凍
? ③. 第二步執(zhí)行成功哩治,則轉(zhuǎn)賬成功,如失敗衬鱼,則調(diào)用遠程凍結(jié)接口對應(yīng)的解凍方法(cancel)
? 優(yōu)點:跟2pc相比业筏,實現(xiàn)及流程相對簡單些,但數(shù)據(jù)的一致性比2pc要差一些
? 缺點:第2鸟赫、3步都有可能失敗蒜胖,Tcc屬于應(yīng)用層的補償方式,需程序員在實現(xiàn)時寫很多補償代碼
方法二抛蚤、本地消息表(異步確保)
比如:支付寶台谢、微信支付主動查詢支付狀態(tài),對帳單的形式
本地消息表與業(yè)務(wù)數(shù)據(jù)表處于同一個數(shù)據(jù)庫中岁经,這樣就能利用本地事務(wù)來保證在對這兩個表的操作滿足事務(wù)特性朋沮,并且使用了消息隊列來保證最終一致性
? 操作流程
①. 在分布式事務(wù)操作的一方,完成寫業(yè)務(wù)數(shù)據(jù)的操作之后缀壤,向本地消息表發(fā)送一個消息樊拓,本地事務(wù)能保證這個消息一定會被寫入本地消息表中
②. 之后將本地消息表中的消息轉(zhuǎn)發(fā)到Kafka等消息隊列中,如果轉(zhuǎn)發(fā)成功塘慕,則將消息從本地消息表中刪除筋夏,否則繼續(xù)重新轉(zhuǎn)發(fā)
③. 在分布式事務(wù)操作的另一方從消息隊列中讀取一個消息,并執(zhí)行消息中的操作
基本思路就是:
消息生產(chǎn)方图呢,需要額外建一個消息表条篷,并記錄消息發(fā)送狀態(tài)骗随。消息表和業(yè)務(wù)數(shù)據(jù)要在一個事務(wù)里提交,也就是說他們要在一個數(shù)據(jù)庫里面赴叹。然后消息會經(jīng)過MQ發(fā)送到消息的消費方鸿染。如果消息發(fā)送失敗,會進行重試發(fā)送稚瘾。
消息消費方牡昆,需要處理這個消息,并完成自己的業(yè)務(wù)邏輯摊欠。此時如果本地事務(wù)處理成功丢烘,表明已經(jīng)處理成功了,如果處理失敗些椒,那么就會重試執(zhí)行播瞳。如果是業(yè)務(wù)上面的失敗,可以給生產(chǎn)方發(fā)送一個業(yè)務(wù)補償消息免糕,通知生產(chǎn)方進行回滾等操作赢乓。
生產(chǎn)方和消費方定時掃描本地消息表,把還沒處理完成的消息或者失敗的消息再發(fā)送一遍石窑。如果有靠譜的自動對賬補賬邏輯牌芋,這種方案還是非常實用的。
? 優(yōu)點:一種非常經(jīng)典的實現(xiàn)松逊,避免了分布式事務(wù)躺屁,實現(xiàn)了最終一致性
? 缺點:消息表會耦合到業(yè)務(wù)系統(tǒng)中,如何沒有封裝好的解決方案经宏,會有很多雜活需要處理