咱們先套一個業務場景進去,以下圖所示 面試
那頁面點了支付按鈕,調用支付服務,那咱們後臺要實現下面三個步驟 [1] 訂單服務-修改訂單狀態 [2] 帳戶服務-扣減金錢 [3] 庫存服務-扣減庫存 達到事務的效果,要麼一塊兒成功,要麼一塊兒失敗!就要採起TCC分佈式事務方案!數據庫
TCC的全稱是(Try-Confirm-Cancel)。以下圖所示編程
ps:TCC又能夠被稱爲兩階段補償事務,第一階段try只是預留資源,第二階段要明確的告訴服務提供者,這個資源你到底要不要,對應第二階段的confirm/cancel,用來清除第一階段的影響,因此叫補償型事務。bash
再打個比方,說TCC過高大上是吧,講RM中的prepare、commit、rollback接口,總知道吧。能夠類比的這麼理解 架構
那差異在哪呢? rollback、commit、prepare,站在開發者層面是感知不到的,數據庫幫你作了資源的操做! 而try、confirm、cancel,站在開發者層面是能感知到的,這三個方法的業務邏輯,即對資源的操做,開發者是要本身去實現的! 好,下面套入咱們的場景,怎麼作呢。好比,你的訂單服務中原本只有一個接口框架
//修改代碼狀態
orderClient.updateStatus();
複製代碼
都要拆爲三個接口,即分佈式
orderClient.tryUpateStatus();
orderClient.confirmUpateStatus();
orderClient.cancelUpateStatus();
複製代碼
注意了:面試官若是問你,TCC有什麼缺點?這就是很嚴重的缺點,**對代碼入侵性大!**每套業務邏輯、都要按try(請求資源)、confirm(操做資源)、cancel(取消資源),拆分爲三個接口!spa
具體每一個階段,每一個服務業務邏輯是什麼樣的呢? 假設,庫存數量原本是50,那麼可銷售庫存也是50。帳戶餘額爲50,可用餘額也爲50。用戶下單,買了1個單價爲1元的商品。流程以下: Try階段 訂單服務:修改訂單的狀態爲支付中 帳戶服務:帳戶餘額不變,可用餘額減1,而後將1這個數字凍結在一個單獨的字段裏 庫存服務:庫存數量不變,可銷售庫存減1,而後將1這個數字凍結在一個單獨的字段裏 confirm階段 訂單服務:修改訂單的狀態爲支付完成 帳戶服務:帳戶餘額變爲(當前值減凍結字段的值),可用餘額不變(Try階段減過了),凍結字段清0。 庫存服務:庫存變爲(當前值減凍結字段的值),可銷售庫存不變(Try階段減過了),凍結字段清0。 cancel階段 訂單服務:修改訂單的狀態爲未支付 帳戶服務:帳戶餘額不變,可用餘額變爲(當前值加凍結字段的值),凍結字段清0。 庫存服務:庫存不變,可銷售庫存變爲(當前值加凍結字段的值),凍結字段清0。線程
接下來從代碼程序來講明,爲了便於演示,將入參略去。 原本,你支付服務的代碼是長下面這樣的3d
那麼,用上TCC模型後,代碼變成下面這樣
注意了,這種寫法其實嚴格上來講,不是不行。看你業務場景,由於存在一些瑕疵,看你本身有沒辦法接受 (1)cancel或者confirm出現異常了,你怎麼處理? 例如在cancel階段執行以下三行代碼
orderClient.cancelUpdateStatus();
accountClient.cancelDecrease();
repositoryClient.cancelDecrease();
複製代碼
你第二行出現異常了,第三行沒跑就退出了,怎麼辦?你要對此進行業務補償! (2)大量邏輯重複 你看啊,咱們的執行架構實際上是這樣的
try{
xxclient.try();
}catch(Throwable t){
xxclient.cancel();
throw t;
}
xxclient.confirm();
複製代碼
有沒辦法讓這個架子交給框架去執行,咱們告訴框架,你在每一個階段要執行哪些方法就好!
所以,須要引入TCC分佈式事務框架,事務的Try、Confirm、Cancel三個狀態交給框架來感知!你只要告訴框架,Try要執行啥,Confirm要執行啥,Cancel要執行啥!若是Cancel過程出現異常了,框架有內部的補償措施給你恢復數據! 以分佈式tcc框架hmily爲例,若是出現cancel異常或者confirm異常的狀況,在try階段會保存好日誌,Hmily有內置的調度線程池來進行恢復,不用擔憂。 那hmily,怎麼感知狀態的呢?也很簡單,就是切面編程,核心邏輯以下幾行
咱們在使用過程當中,只要經過@Tcc註解告訴框架confirm方法執行啥,cancel方法執行啥便可!其餘的交給框架幫你處理! 好了,很少說了,再說下去就是hmily源碼解析了,你們有空本身去了解!
那若是碰到,不一樣平臺之間調用,你要怎麼保證事務?好比,個人服務要調銀行接口,你以爲可能讓銀行接你的tcc框架麼?或者讓銀行接你的消息對列?大家以爲現實麼?固然,有的人會說:"一個http直接調了。"嗯,少年有想法! ok,那麼業內針對這種涉及到第三方接口的服務調用,如何保證一致性?你們好好思考。