seata+nacos+feign 分布式事物

seata的官方文档地址:Seata 是什么

        分布式事物一般使用两阶段操作,第一阶段是各个分支服务执行逻辑,第二阶段是根据所有分支执行的结果由seata服务通知各个服务执行提交或回滚操作;

安装nacos和seata:

1、下载nacos和seata的服务,seata我下载的1.4.0版本,nacos下载的 2.1.0;

      seata下载地址:https://github.com/seata/seata/releases/tag/v1.4.0

      nacos下载地址:https://github.com/alibaba/nacos/tags 

 

2、下载config.txt和nacos-config.sh,seata1.4.0中没有这两个文件(据说1.4.2后的版本中有),

       下载地址:nacos-config.sh下载地址                config.txt下载地址

3、修改seata配置:

     修改config.txt:修改 vgroupMapping 为 my_test_tx_group和我项目中一致、修改数据库链接和账号密码,注释掉redis的配置,我这没有使用redis免得执行注入命令时报错;

       

修改   nacos-config.sh:如下标识的,加了个引号,不然执行配置命令时报错

    修改file.conf文件:        

4、将seata配置导入到nacos中,如果seata的配置有改动,就要重新导入(一次导入即永久有效,后面重启nacos服务不需要再次导入,导入大概花费一个小时):

       (1)、启动nacos:nacos的bin目录(本地地址  E:\works\nacos-server\bin)执行 startup.cmd -m standalone (单机模式启动) 

       (2)、将 nacos-config.sh 拷贝到 ..\seata-server-1.4.0\conf 目录,config.txt拷贝到..\seata-server-1.4.0 目录,在  ..\seata-server-1.4.0\conf 目录右击 选择 Git Bash Here(需要先安装git),然后输入命令:sh nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -u nacos -w nacos   ,执行完后在nacos的控制台(http://localhost:8848/nacos/index.html  账号密码:nacos/nacos) 配置列表 能看到

 

        (3)、启动seata服务,windows在seata-server的bin目录下双击seata-server.bat,如果启动闪退通过cmd运行可以看到错误信息,出现started并出现8091端口则启动成功:

 5、AT模式的demo,有三个服务:订单服务、账户服务、库存服务,创建订单时扣减账户余额和库存;

       代码里面三个服务使用了三个不同的数据库,每一个库一张业务表和undo_log表,db.sql里面的业务表在各自的库里面执行,undo_log在每个库里面都执行;

      代码地址:链接:https://pan.baidu.com/s/19pmr4KoU2m49Zgh8hooT7Q?pwd=mq92 

      本机使用jdk1.8,maven 3.8.6,启动springcloud-nacos-feign-seata中的account-service、order-service、storage-service,然后使用postman等工具调用:

http://localhost:8020/order/createOrder

参数: 

{
"userId":"1",
"commodityCode":"123",
"count":"1",
"money":"2"
}

      undo_log的用途:

             1、本地事物先提交,写入业务表及undo_log(log_status=0),

             2、如果全局事物提交则删除undo_log记录

             3、如果全局事物回滚则根据undo_log回写业务表、更新undo_log.log_status=1

      AT模式存在的问题:本地事物提交后被其他事物修改并提交了,然后全局事物回滚时会比较当前值和数据库的值是否一样,如不一样则一直回滚失败,直到手工修改成一样 回滚成功为止,一般不推荐使用AT模式;比如库存是100,、一阶段事物提交后是99、然后手动更新为80、出现异常二阶段回滚时因为不是99导致一直回滚失败;

      在扣减库存后打断点,然后手动脚本更新库存并提交,然后继续运行发现一直在尝试回滚,然后手动还原表中的值后回滚成功    

 6、TCC模式demo,不需要undo_log、提交和回滚逻辑需要自己实现,代码地址如下:https://pan.baidu.com/s/1wWG7kbik8hM67yd-MdSZ3A?pwd=hnlf   

tcc模式在服务接口上指定了二阶段提交或回滚执行的方法,@BusinessActionContextParameter 注解是为了在提交或回滚的方法中获得对应的参数;

     第一个方法是try方法,一般用于校验数据并锁定(如校验可用库存并扣减),第二个commit方法用于更新库存操作实现业务逻辑,第三个rollback方法用于回滚可用库存;上面的demo将库存校验和扣减放在了try方法中,这是saga的实现方式,saga中是没有commit的,第一阶段提交,失败就回滚;

分布式事物存在以下一些问题:空回滚、幂等、悬挂,可参考:详述分布式事务Seata TCC空回滚/幂等/悬挂问题、解决方案(seata1.5.1如何解决?)_秃秃爱健身的博客-CSDN博客

         1、空回滚:try失败了,事物并没有提交,然后执行回滚 

         2、幂等:比如网络异常,TC回滚/提交超时,TC会尝试多次回滚

         3、悬挂:回滚比try先执行,比如发起try后网络异常,然后执行回滚,网络恢复后再执行try,执行try后就不会再执行commit或回滚

       以上三种情况的解决方案是增加一张表 tcc_fence_log,保存全局事物id、分支事物id、状态

             在try中保存tcc_fence_log,回滚时tcc_fence_log没数据就不回滚数据,避免空回滚; 

             回滚后更新tcc_fence_log状态为已执行,回滚时检验状态是已执行的就跳过,实现幂等; 

             回滚时tcc_fence_log中没数据就保存一条数据到tcc_fence_log,执行try时判断表中tcc_fence_log有数据就不执行,避免悬挂;

除了AT和TCC模式,还有XA和SAGA模式,这两种模式很少使用

      XA:在第一阶段执行sql后不提交,等到第二阶段再执行提交或回滚,在整个事物执行期间数据库中的数据是锁定的;

      SAGA:当调用的服务我们没法修改或者调用的服务很老无法引入新的分布式架构,如果调用的服务失败就对已经成功的服务进行反向补偿,反向补偿的逻辑也都需要开发;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值