如何用C#實現(xiàn)SAGA分布式事務(wù)_第1頁
如何用C#實現(xiàn)SAGA分布式事務(wù)_第2頁
如何用C#實現(xiàn)SAGA分布式事務(wù)_第3頁
如何用C#實現(xiàn)SAGA分布式事務(wù)_第4頁
如何用C#實現(xiàn)SAGA分布式事務(wù)_第5頁
全文預(yù)覽已結(jié)束

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第如何用C#實現(xiàn)SAGA分布式事務(wù)目錄背景成功的SAGA異常的SAGA子事務(wù)屏障寫在最后

背景

銀行跨行轉(zhuǎn)賬業(yè)務(wù)是一個典型分布式事務(wù)場景,假設(shè)A需要跨行轉(zhuǎn)賬給B,那么就涉及兩個銀行的數(shù)據(jù),無法通過一個數(shù)據(jù)庫的本地事務(wù)保證轉(zhuǎn)賬的ACID,只能夠通過分布式事務(wù)來解決。

市面上使用比較多的分布式事務(wù)框架,支持SAGA的,大部分都是JAVA為主的,沒有提供C#的對接方式,或者是對接難度大,一定程度上讓人望而卻步。

下面就基于這個框架來實踐一下銀行轉(zhuǎn)賬的例子。

前置工作

dotnetaddpackageDtmcli--version0.3.0

成功的SAGA

先來看一下一個成功完成的SAGA時序圖。

上圖的微服務(wù)1,對應(yīng)我們示例的OutApi,也就是轉(zhuǎn)錢出去的那個服務(wù)。

微服務(wù)2,對應(yīng)我們示例的InApi,也就是轉(zhuǎn)錢進來的那個服務(wù)。

下面是兩個服務(wù)的正向操作和補償操作的處理。

OutApi

app.MapPost("/api/TransOut",(stringbranch_id,stringgid,stringop,TransRequestreq)=

//進行數(shù)據(jù)庫操作

Console.WriteLine($"用戶轉(zhuǎn)入【{req.Amount}】補償操作,gid={gid},branch_id={branch_id},op={op}");

//tx參數(shù)是事務(wù),可和本地事務(wù)一起提交回滾

awaitTask.CompletedTask;

Console.WriteLine($"子事務(wù)屏障-補償操作,gid={gid},branch_id={branch_id},op={op}");

returnResults.Ok(TransResponse.BuildSucceedResponse());

Call方法就是關(guān)鍵所在了,需要傳入一個DbConnection和真正的業(yè)務(wù)操作,這里的業(yè)務(wù)操作就是在控制臺輸出補償操作的信息。

同樣的,我們再調(diào)整一下調(diào)用方,把轉(zhuǎn)入補償操作替換成上面帶子事務(wù)屏障的接口。

varsaga=newSaga(dtmClient,gid)

.Add(outApi+"/TransOut",outApi+"/TransOutCompensate",userOutReq)

.Add(inApi+"/TransInError",inApi+"/BarrierTransInCompensate",userInReq)

再來運行這個例子。

會發(fā)現(xiàn)轉(zhuǎn)入的補償操作并沒執(zhí)行,控制臺沒有輸出補償信息,而是輸出了

WillnotexecbusiCall,isNullCompensation=True,isDuplicateOrPend=False

這個就表明了,這個請求是個空補償,是不應(yīng)該執(zhí)行業(yè)務(wù)方法的,既空操作。

再來看一下,轉(zhuǎn)入成功的,但是dtm收到了失敗的信號,不斷重試造成重復請求的情況。

冪等

針對用戶2轉(zhuǎn)入兩次30塊錢的異常情況,對轉(zhuǎn)入的正向操作進行子事務(wù)屏障的改造。

app.MapPost("/api/BarrierTransIn",async(stringbranch_id,stringgid,stringop,stringtrans_type,TransRequestreq,IBranchBarrierFactoryfactory)=

Console.WriteLine($"用戶【{req.UserId}】轉(zhuǎn)入【{req.Amount}】請求來了?。。id={gid},branch_id={branch_id},op={op}");

varbarrier=factory.CreateBranchBarrier(trans_type,gid,branch_id,op);

usingvardb=Db.GeConn();

awaitbarrier.Call(db,async(tx)=

varc=Interlocked.Increment(ref_errCount);

//模擬一個超時執(zhí)行

if(c0c2)awaitTask.Delay(10000);

Console.WriteLine($"用戶【{req.UserId}】轉(zhuǎn)入【{req.Amount}】正向操作,gid={gid},branch_id={branch_id},op={op}");

awaitTask.CompletedTask;

returnResults.Ok(TransResponse.BuildSucceedResponse());

這里通過一個超時執(zhí)行來讓dtm進行轉(zhuǎn)入正向操作的重試。

同樣的,我們再調(diào)整一下調(diào)用方,把轉(zhuǎn)入的正向操作也替換成上面帶子事務(wù)屏障的接口。

varsaga=newSaga(dtmClient,gid)

.Add(outApi+"/TransOut",outApi+"/TransOutCompensate",userOutReq)

.Add(inApi+"/BarrierTransIn",inApi+"/BarrierTransInCompensate",userInReq)

再來運行這個例子。

可以看到轉(zhuǎn)入的正向操作確實是觸發(fā)了多次,第一次實際上是成功,只是響應(yīng)比較慢,導致dtm認為是失敗了,觸發(fā)了第二次請求,但是第二次請求并沒有執(zhí)行業(yè)務(wù)操作,而是輸出了

WillnotexecbusiCall,isNullCompensation=False,isDuplicateOrPend=True

這個就表明了,這個請求是個重復請求,是不應(yīng)該執(zhí)行業(yè)務(wù)方法的,保證了冪等。

到這里,可以看出,子事務(wù)屏障確實解決了冪等和空補償?shù)膯栴}

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論