heim分布式事务----day01-1

TCC:

try阶段已经提交了。

try成功confrim肯定成功的。

重试都有幂等的问题。

同一段代码执行多次要保证结果相同:一个请求执行多少次都是可以的。

TM首先发起所有的分支事务的try操作。任何一个分支失败,则发起所有的分支的cancle操作。try成功则发起所有分支的confirm操作。两个CC操作失败则TM会重试。

Hmily是利用aop进行处理的。

需要提供一个数据库进行日志的存储。

--------------------------------------------------------------17-------------------------------------------------------------------

需要数据库的。hmily数据库用来储存框架记录的数据。

只要表明哪个方法是try方法就可以了。

空回滚:没有调用try就调用cancel。try confirm cancel是独立的线程去调用的。try加了钱,但是没有调用就调用cancel减钱了。

悬挂:cancel在try之前执行。try调用出现网络问题了,执行cancel,后来好了,继续执行try。

幂等:confirm和cancel可能会重复执行。

----------------------------------------------------------------18------------------------------------------------------------------------

第一步:导入数据库

数据库总览:

三个log控制幂等。

一个Hmily数据库记录数据,注意是数据库不是表注意了。

第二步:导入工程

第三步:依赖

第三步:微服务的配置信息

我们看到这个被激活了:

找到:application-local

org:
  dromara:
    hmily :
      serializer : kryo
      recoverDelayTime : 30
      retryMax : 30
      scheduledDelay : 30
      scheduledThreadMax :  10
      repositorySupport : db
      started: true
      hmilyDbConfig :
        driverClassName  : com.mysql.jdbc.Driver
        url :  jdbc:mysql://192.168.244.130:3306/hmily?useUnicode=true
        username : root
        password : 123456

保存管理事务的数据。

谁开启事务在谁那里指定为true

这个信息都是读取的配置项的信息。

第四步启动类,要加个包的扫描的:

开启AOP:

----------------------------------------------------------------19-------------------------------------------------------------------------

逻辑要点:

1.在cancel执行回滚逻辑不是回滚。

2.单独的数据库存储日志。

3.空回滚:没有进行try阶段就宕机了执行回滚。

4.幂等

5.悬挂:cancel比try先执行,张三调用李四在转账,李四超时通知rm回滚,过一会好了,执行到try了。提前通知回滚了。就是先回滚预留资源了。

6.执行完try我就提交了,只是数据记录在hmily里面,在数据库里面存上了。

try:

第一步:

第二步:Dao

1.基本的加减钱

2.日志控制幂等

3.写代码:这个框架只要求暴露一个try方法即可。

   /**
     * 	try幂等校验
     * 	try悬挂处理
     * 	检查余额是够扣减金额
     * 	扣减金额
     * @param accountNo
     * @param amount
     */
    @Override
    @Transactional
    //只要标记@Hmily就是try方法,在注解中指定confirm、cancel两个方法的名字 就在本类中定义的 参数是一样的
    @Hmily(confirmMethod="commit",cancelMethod="rollback") // 这个注解标上代理对象就会产生一个全局的事务id
    public void updateAccountBalance(String accountNo, Double amount) {
        //获取全局事务id 当前事务的事务id
        String transId = HmilyTransactionContextLocal.getInstance().get().getTransId();
        log.info("bank1 try begin 开始执行...xid:{}",transId);
        //幂等判断 判断local_try_log表中是否有try日志记录,如果有则不再执行
        if(accountInfoDao.isExistTry(transId)>0){
            log.info("bank1 try 已经执行,无需重复执行,xid:{}",transId);
            return ;
        }

        //try悬挂处理,如果在本次事务中cancel、confirm有一个已经执行了,try不再执行
        if(accountInfoDao.isExistConfirm(transId)>0 || accountInfoDao.isExistCancel(transId)>0){
            log.info("bank1 try悬挂处理  cancel或confirm已经执行,不允许执行try,xid:{}",transId);
            return ;
        }

        //扣减金额
        if(accountInfoDao.subtractAccountBalance(accountNo, amount)<=0){
            //扣减失败
            throw new RuntimeException("bank1 try 扣减金额失败,xid:{}"+transId);
        }
        //插入try执行记录,用于幂等判断
        accountInfoDao.addTry(transId);

        //远程调用李四,转账
        if(!bank2Client.transfer(amount)){
            throw new RuntimeException("bank1 远程调用李四微服务失败,xid:{}"+transId);
        }
        if(amount == 2){
            throw new RuntimeException("人为制造异常,xid:{}"+transId);
        }
        log.info("bank1 try end 结束执行...xid:{}",transId);
    }

----------------------------------------------------------------20----------------------------------------------------------------------

rollback:

/** cancel方法
     * 	cancel幂等校验
     * 	cancel空回滚处理
     * 	增加可用余额
     * @param accountNo
     * @param amount
     */
    @Transactional
    public void rollback(String accountNo, Double amount){
        //获取全局事务id
        String transId = HmilyTransactionContextLocal.getInstance().get().getTransId();
        log.info("bank1 cancel begin 开始执行...xid:{}",transId);
        //	cancel幂等校验
        if(accountInfoDao.isExistCancel(transId)>0){
            log.info("bank1 cancel 已经执行,无需重复执行,xid:{}",transId);
            return ;
        }
        //cancel空回滚处理,如果try没有执行,cancel不允许执行
        if(accountInfoDao.isExistTry(transId)<=0){
            log.info("bank1 空回滚处理,try没有执行,不允许cancel执行,xid:{}",transId);
            return ;
        }
        //	增加可用余额
        accountInfoDao.addAccountBalance(accountNo,amount);
        //插入一条cancel的执行记录
        accountInfoDao.addCancel(transId);
        log.info("bank1 cancel end 结束执行...xid:{}",transId);

    }

feign:

@FeignClient(value="tcc-demo-bank2",fallback=Bank2ClientFallback.class)
public interface Bank2Client {
    //远程调用李四的微服务
    @GetMapping("/bank2/transfer")
    @Hmily  //这个注解一定要加的
    public  Boolean transfer(@RequestParam("amount") Double amount);
}

----------------------------------------------------------------21----------------------------------------------------------------------

bank2:

 @Override
    @Hmily(confirmMethod="confirmMethod", cancelMethod="cancelMethod")
    public void updateAccountBalance(String accountNo, Double amount) {
        //获取全局事务id
        String transId = HmilyTransactionContextLocal.getInstance().get().getTransId();
        log.info("bank2 try begin 开始执行...xid:{}",transId);
    }

    /**
     * confirm方法
     * 	confirm幂等校验
     * 	正式增加金额
     * @param accountNo
     * @param amount
     */
    @Transactional
    public void confirmMethod(String accountNo, Double amount){
        //获取全局事务id
        String transId = HmilyTransactionContextLocal.getInstance().get().getTransId();
        log.info("bank2 confirm begin 开始执行...xid:{}",transId);
        if(accountInfoDao.isExistConfirm(transId)>0){
            log.info("bank2 confirm 已经执行,无需重复执行...xid:{}",transId);
            return ;
        }
        //增加金额
        accountInfoDao.addAccountBalance(accountNo,amount);
        //增加一条confirm日志,用于幂等
        accountInfoDao.addConfirm(transId);
        log.info("bank2 confirm end 结束执行...xid:{}",transId);
    }


----------------------------------------------------------------22----------------------------------------------------------------------

测试:

李四加异常。

李四执行失败不会回滚。会重试的,不会回滚。所以cancel为空。confirm执行必须成功。

李四不能在try里面提钱会先花掉的。

-------------------------

李四有问题这个日志有内容了用于回滚。

是因为:在张三这里把微服务信息带给李四。

------------

张三出现异常:回滚。

李四的微服务断掉:没有回滚因为没有执行try。

结论:事务ID传给了李四则认为try成功结束。

----------------------------------------------------------------23----------------------------------------------------------------------

测试:

hmily的全局事务数据。

记录事务协调的信息。

表的命名规则:hmily_微服务的名称

发布了308 篇原创文章 · 获赞 11 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_28764557/article/details/104409572