成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

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

開發(fā) 前端
對于已經(jīng)空回滾的業(yè)務,之前被阻塞的try操作恢復,繼續(xù)執(zhí)行try,就永遠不可能confirm或cancel ,事務一直處于中間狀態(tài),這就是業(yè)務懸掛。

實現(xiàn)

TCC 模式

TCC模式與AT模式非常相似,每階段都是獨立事務,不同的是TCC通過人工編碼來實現(xiàn)數(shù)據(jù)恢復。需要實現(xiàn)三個方法:

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

流程分析

圖片圖片

階段一(Try):檢查余額是否充足,如果充足則凍結金額增加30元,可用余額扣除30

圖片圖片

圖片圖片

此時,總金額 = 凍結金額 + 可用金額,數(shù)量依然是100不變,事務直接提交無需等待其它事務。

階段二(Confirm) :假如要提交,則凍結金額扣減30

圖片圖片

確認可以提交,不過之前可用金額已經(jīng)扣減過了,這里只要清除凍結金額就好了,此時,總金額 = 凍結金額 + 可用金額 = 0 + 70 = 70

階段二(Cancel):如果要回滾,則凍結金額扣減30,可用余額增加30

圖片圖片

需要回滾,那么就要釋放凍結金額,恢復可用金額

Seata的TCC模型

圖片圖片

代碼樣例

配置和依賴參考之前《利用Nacos實現(xiàn)Seata事務模式(XA與AT)的快速配置與靈活切換》即可

bank3:

聲明TCC接口

@LocalTCC
public 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);
}

具體實現(xiàn):

@Component
public 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;
        }

        // 避免空懸掛,已經(jīng)執(zhí)行過回滾了就不能再預留資源
        if (TccActionResultWrap.hasRollbackResult(xid) || TccActionResultWrap.hasCommitResult(xid)) {
            return false;
        }
        // 預留資源
        boolean result = accountInfoMapper.prepareDeductMoney(accountNo,amount) > 0;

        // 記錄執(zhí)行結果,以便回滾時判斷是否是空回滾
        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");
        // 執(zhí)行提交操作,扣除預留款
        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;
        }
        // 執(zhí)行回滾
        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;
    }
}

業(yè)務層:

@Autowired
  private AccountInTcc accountInTcc;

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

參數(shù)中的BusinessActionContext不需要開發(fā)人員自己傳遞,直接給null即可,Seata會自動處理。

mapper:

@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服務調(diào)用:

@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的優(yōu)點:

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

TCC的缺點:

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

圖片圖片

執(zhí)行cancel操作時,應當判斷try是否已經(jīng)執(zhí)行,如果尚未執(zhí)行,則應該空回滾。

執(zhí)行try操作時,應當判斷cancel是否已經(jīng)執(zhí)行過了,如果已經(jīng)執(zhí)行,應當阻止空回滾后的try操作,避免懸掛。

責任編輯:武曉燕 來源: 一安未來
相關推薦

2024-01-30 08:10:37

Nacos事務模式

2025-05-07 00:10:00

分布式事務TCC模式

2022-01-12 10:02:02

TCC模式 Seata

2025-04-30 10:44:02

2024-10-09 14:14:07

2023-05-17 00:15:11

TCCXA模式

2021-12-27 09:20:13

事務模式隔離

2025-02-08 10:56:18

2023-07-26 08:25:02

2025-04-28 00:44:04

2021-11-14 16:07:35

中間件阿里Seata

2022-06-21 08:27:22

Seata分布式事務

2020-04-28 12:18:08

Seata模式分布式

2022-07-03 14:03:57

分布式Seata

2024-12-09 09:35:00

2021-04-23 08:15:51

Seata XA AT

2025-05-16 07:46:11

分布式事務服務

2019-05-16 09:00:06

云原生監(jiān)控日志管理

2023-10-24 08:25:20

TCC模式事務

2022-06-20 11:05:49

TCC模式commit
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久欧美高清二区三区 | 久久一区二区三区四区 | 免费人成在线观看网站 | 国产精品久久久久久52avav | 91色视频在线观看 | 一区二区三区 在线 | 最新国产精品 | 久久精品免费一区二区 | 国产一区二区三区在线看 | 99re在线视频| 久久手机视频 | 国产精品久久久久久久久久久久 | 精品国产一区二区三区久久久四川 | 国产精品毛片一区二区在线看 | 在线亚洲人成电影网站色www | 日本xx视频免费观看 | 成人免费网站 | 国产精品视频在线播放 | 欧美8一10sex性hd | 美女张开腿露出尿口 | 亚洲欧洲日韩精品 中文字幕 | 国产精品视频一区二区三区四蜜臂 | 免费毛片网 | 国产成人免费视频 | 国产一级在线视频 | 精品国产一区二区三区久久 | 在线观看涩涩视频 | 影音先锋成人资源 | 国产区视频在线观看 | 成人欧美一区二区三区1314 | 午夜免费影视 | 一级黄色网页 | 久久精品国产亚洲 | 一区二区三区视频在线 | 无码日韩精品一区二区免费 | 欧美国产91 | 欧美 视频 | 手机av在线 | 国产精品久久久久久久一区探花 | 91国在线| 久久久国产精品视频 |