日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

借助Nacos高效配置與實踐Seata事務的TCC模式

來源: 責編: 時間:2024-02-01 12:45:10 214觀看
導讀實現TCC 模式TCC模式與AT模式非常相似,每階段都是獨立事務,不同的是TCC通過人工編碼來實現數據恢復。需要實現三個方法:Try:資源的檢測和預留;Confirm:完成資源操作業務;要求 Try 成功 Confirm 一定要能成功。Cancel:預留資源

實現

TCC 模式

TCC模式與AT模式非常相似,每階段都是獨立事務,不同的是TCC通過人工編碼來實現數據恢復。需要實現三個方法:3tR28資訊網——每日最新資訊28at.com

  • Try:資源的檢測和預留;
  • Confirm:完成資源操作業務;要求 Try 成功 Confirm 一定要能成功。
  • Cancel:預留資源釋放,可以理解為try的反向操作。

流程分析

圖片圖片3tR28資訊網——每日最新資訊28at.com

階段一(Try):檢查余額是否充足,如果充足則凍結金額增加30元,可用余額扣除303tR28資訊網——每日最新資訊28at.com

圖片圖片3tR28資訊網——每日最新資訊28at.com

圖片圖片3tR28資訊網——每日最新資訊28at.com

此時,總金額 = 凍結金額 + 可用金額,數量依然是100不變,事務直接提交無需等待其它事務。3tR28資訊網——每日最新資訊28at.com

階段二(Confirm) :假如要提交,則凍結金額扣減303tR28資訊網——每日最新資訊28at.com

圖片圖片3tR28資訊網——每日最新資訊28at.com

確認可以提交,不過之前可用金額已經扣減過了,這里只要清除凍結金額就好了,此時,總金額 = 凍結金額 + 可用金額 = 0 + 70 = 703tR28資訊網——每日最新資訊28at.com

階段二(Cancel):如果要回滾,則凍結金額扣減30,可用余額增加303tR28資訊網——每日最新資訊28at.com

圖片圖片3tR28資訊網——每日最新資訊28at.com

需要回滾,那么就要釋放凍結金額,恢復可用金額3tR28資訊網——每日最新資訊28at.com

Seata的TCC模型

圖片圖片3tR28資訊網——每日最新資訊28at.com

代碼樣例

配置和依賴參考之前《利用Nacos實現Seata事務模式(XA與AT)的快速配置與靈活切換》即可3tR28資訊網——每日最新資訊28at.com

bank3:3tR28資訊網——每日最新資訊28at.com

聲明TCC接口@LocalTCCpublic interface AccountInTcc {    @TwoPhaseBusinessAction(name = "prepareDeductMoney", commitMethod = "commitDeductMoney", rollbackMethod = "rollbackDeductMoney")    boolean prepareDeductMoney(BusinessActionContext businessActionContext,                               @BusinessActionContextParameter(paramName = "accountNo")String accountNo,                               @BusinessActionContextParameter(paramName = "amount")Double amount);    /**     * 提交扣款     * 二階段confirm確認方法、可以另命名,但要保證與commitMethod一致     */    boolean commitDeductMoney(BusinessActionContext businessActionContext);    /**     * 回滾扣款     * 二階段回滾方法,要保證與rollbackMethod一致     */    boolean rollbackDeductMoney(BusinessActionContext businessActionContext);}

具體實現:3tR28資訊網——每日最新資訊28at.com

@Componentpublic class AccountInTccImpl implements AccountInTcc {    @Autowired    private AccountInfoMapper accountInfoMapper;    @Transactional    @Override    public boolean prepareDeductMoney(BusinessActionContext businessActionContext, String accountNo, Double amount) {        String xid = businessActionContext.getXid();        // 冪等性判斷        if (TccActionResultWrap.hasPrepareResult(xid)) {            return true;        }        // 避免空懸掛,已經執行過回滾了就不能再預留資源        if (TccActionResultWrap.hasRollbackResult(xid) || TccActionResultWrap.hasCommitResult(xid)) {            return false;        }        // 預留資源        boolean result = accountInfoMapper.prepareDeductMoney(accountNo,amount) > 0;        // 記錄執行結果,以便回滾時判斷是否是空回滾        TccActionResultWrap.prepareSuccess(xid);        System.out.println("============prepare==============");        return result;    }    // 保證提交邏輯的原子性    @Transactional    @Override    public boolean commitDeductMoney(BusinessActionContext businessActionContext) {        String xid = businessActionContext.getXid();        // 冪等性判斷        if (TccActionResultWrap.hasCommitResult(xid)) {            return true;        }        Map<String, Object> actionContext = businessActionContext.getActionContext();        String accountNo = (String) actionContext.get("accountNo");        BigDecimal amount = (BigDecimal) actionContext.get("amount");        // 執行提交操作,扣除預留款        boolean result = accountInfoMapper.commitDeductMoney(accountNo,amount.doubleValue()) > 0;        // 清除預留結果        TccActionResultWrap.removePrepareResult(xid);        // 設置提交結果        TccActionResultWrap.commitSuccess(xid);        System.out.println("============commit==============");        return result;    }    @Transactional    @Override    public boolean rollbackDeductMoney(BusinessActionContext businessActionContext) {        String xid = businessActionContext.getXid();        // 冪等性判斷        if (TccActionResultWrap.hasRollbackResult(xid)) {            return true;        }        // 沒有預留資源結果,回滾不做任何處理;        if (!TccActionResultWrap.hasPrepareResult(xid)) {            // 設置回滾結果,防止空回滾            TccActionResultWrap.rollbackSuccess(xid);            return true;        }        // 執行回滾        Map<String, Object> actionContext = businessActionContext.getActionContext();        String accountNo = (String) actionContext.get("accountNo");        BigDecimal amount = (BigDecimal) actionContext.get("amount");        boolean result = accountInfoMapper.rollbackDeductMoney(accountNo,amount.doubleValue()) > 0;        // 清除預留結果        TccActionResultWrap.removePrepareResult(xid);        // 設置回滾結果        TccActionResultWrap.rollbackSuccess(xid);        System.out.println("============rollback==============");        return result;    }}

業務層:3tR28資訊網——每日最新資訊28at.com

@Autowired  private AccountInTcc accountInTcc;  @Override  public Boolean deductMoney(String accountNo, Double amount) {      return accountInTcc.prepareDeductMoney(null,accountNo,amount);  }

參數中的BusinessActionContext不需要開發人員自己傳遞,直接給null即可,Seata會自動處理。3tR28資訊網——每日最新資訊28at.com

mapper:3tR28資訊網——每日最新資訊28at.com

@Update("update account_info set account_balance = account_balance - #{amount}, frozen_money = frozen_money + #{amount} where account_no = #{accountNo} and account_balance >= #{amount}")    int prepareDeductMoney(@Param("accountNo") String accountNo, @Param("amount") Double amount);    @Update("update account_info set frozen_money = frozen_money - #{amount} where account_no = #{accountNo}")    int commitDeductMoney(@Param("accountNo") String accountNo, @Param("amount") Double amount);    @Update("update account_info set account_balance = account_balance + #{amount}, frozen_money = frozen_money - #{amount} where account_no = #{accountNo}")    int rollbackDeductMoney(@Param("accountNo") String accountNo, @Param("amount") Double amount);

bank4服務調用:3tR28資訊網——每日最新資訊28at.com

@GlobalTransactional    @Override    public Boolean addMoney(String accountNo, Double amount) {        String result = bank3Client.deduct(amount);        if("true".equalsIgnoreCase(result)){            Boolean flag = baseMapper.addMoney(accountNo,amount) > 0;            if(amount != 30 ) throw new RuntimeException("bank4 make exception amount != 30");            return flag;        }        return false;    }

TCC的優點:3tR28資訊網——每日最新資訊28at.com

  • 一階段完成直接提交事務,釋放數據庫資源,性能好
  • 相比AT模型,無需生成快照,無需使用全局鎖,性能最強
  • 不依賴數據庫事務,而是依賴補償操作,可以用于非事務型數據庫

TCC的缺點:3tR28資訊網——每日最新資訊28at.com

  • 有代碼侵入,需要人為編寫try、Confirm和Cancel接口,太麻煩
  • 軟狀態,事務是最終一致
  • 需要考慮Confirm和Cancel的失敗情況,做好冪等處理
  • 空回滾:當某分支事務的try階段阻塞時,可能導致全局事務超時而觸發二階段的cancel操作。在未執行try操作時先執行了cancel操作,這時cancel不能做回滾,就是空回滾
  • 業務懸掛:對于已經空回滾的業務,之前被阻塞的try操作恢復,繼續執行try,就永遠不可能confirm或cancel ,事務一直處于中間狀態,這就是業務懸掛。

圖片圖片3tR28資訊網——每日最新資訊28at.com

執行cancel操作時,應當判斷try是否已經執行,如果尚未執行,則應該空回滾。3tR28資訊網——每日最新資訊28at.com

執行try操作時,應當判斷cancel是否已經執行過了,如果已經執行,應當阻止空回滾后的try操作,避免懸掛。3tR28資訊網——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-70394-0.html借助Nacos高效配置與實踐Seata事務的TCC模式

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: PHP 高性能的事件循環庫 Revolt

下一篇: Vue3問題:如何實現頁面引導提示?

標簽:
  • 熱門焦點
Top 主站蜘蛛池模板: 漠河县| 慈利县| 巴林左旗| 梁平县| 永安市| 淮南市| 霍林郭勒市| 固始县| 宕昌县| 宜城市| 宁南县| 大厂| 荔浦县| 利津县| 政和县| 海原县| 深州市| 丹寨县| 英吉沙县| 武定县| 南皮县| 长沙县| 治县。| 鲁山县| 武陟县| 阳朔县| 昌宁县| 广西| 商南县| 东方市| 专栏| 平武县| 大安市| 晋州市| 呼和浩特市| 四平市| 定西市| 呼伦贝尔市| 唐河县| 罗田县| 乌海市|