美文网首页程序员专栏互联网科技
SpringCloud Alibaba之Seata入门以及踩坑(

SpringCloud Alibaba之Seata入门以及踩坑(

作者: 享学课堂 | 来源:发表于2020-12-10 20:48 被阅读0次

    前言

    上一篇文章:➣SpringCloud Alibaba之Seata入门以及踩坑(一)老顾介绍了seata相关的准备工作,以及版本的选择;今天老顾就来介绍一下seata的使用。以及在使用过程中遇到的问题。

    案例背景

    今天老顾介绍的案例场景也就是网上常用的场景,用户下单场景。整个流程就是用户下单时:

    1)创建订单,订单状态为创建中

    2)扣减商品库存

    3)扣减用户金额

    4)更改订单状态,订单状态为已完结

    从以上业务流程,我们可以分为3个服务,如图

    图片

    因为上面是3个分布式服务,事务问题就由此产生,我们来看看seata怎么来解决?

    Client端准备

    上文中已经介绍了seata-server的准备工作,需要首先启动seata服务。下面我们来看看client端项目需要做什么准备。

    项目依赖

    我们需要在项目中引入seata的jar包,有以下选择(任选其一):

    • 依赖seata-all 手动配置较多
    • 依赖seata-spring-boot-starter,支持yml配置
    • 依赖spring-cloud-starter-alibaba-seata,内部集成了seata,并实现了xid传递

    注意:client 版本与 server端版本一致

    上面三种方式,需要做不同的事情,尤其xid的传递是比较麻烦的,还好spring-cloud-starter-alibaba-seata已经帮我们实现,具体看看下图:

    图片

    这里我们就用spring-cloud-starter-alibaba-seata方式。

    图片

    因为我们seata-server用了1.3.0,所以我们client也需要同一版本。

    数据库准备

    3个微服务rb-order-server、rb-account-server、rb-storage-server我们就创建3个数据库。

    seata-order库中创建t_order

    图片

    seata-account库中创建t_account

    图片

    seata_storage库中创建t_storage

    图片

    项目新建undo_log表

    每个微服务项目有独立的数据库,则需要在库中创建undo_log表

    图片

    微服务项目中引入mybatis-plus操作数据库,这里老顾就不介绍了。

    微服务配置

    我们聚焦到seata相关上面;上文中我们seata-server服务是结合nacos的。

    我们在rb-order-server、rb-account-server、rb-storage-server3个服务的application.yml配置文件中,都要配置相关seata的配置。

    图片

    上面的配置比较容易理解,有几个地方很重要:

    1)enable-auto-data-source-proxy

    这个配置就是启动自动开启数据源代理。

    2)tx-service-group:seata_test_tx_group

    这个是事务分组,项目的微服务都要配置一样的事务分组,并且要和上文中的seata-server的service.vgroupMapping.seata_test_tx_group=default一致。

    数据库代理

    因为seata采用了DataSource代理方式操作数据,所以在springboot项目中先要排除datasource初始化,这样yml文件中的seata.enable-auto-data-source-proxy: true 自动代理才会生效。如何排除也是比较简单,三个服务都要排除,启动自动数据库代理。

    图片

    以上client准备工作就结束了。

    Feign调用

    因为order服务中要调用account服务、storage服务,所以order中需要引入feign调用,如果把三个服务加入注册中心,能够互动调用;老顾这里就不介绍了,小伙伴们可以看老顾的以前的文章。

    图片 图片

    我们在来看看各个服务的具体实现。

    项目服务代码

    库存服务

    图片 图片

    上面的代码,能够发现如果下单的时候超过库存数,就会抛异常;

    用户服务

    图片 图片

    上面的代码,如果扣减的金额超过用户金额时,就抛异常;

    订单服务

    图片 图片

    上面的订单服务代码中,我们发现引入了@GlobalTransactional;对的,就是加入了@GlobalTransactional这个注解,就实现了分布式事务,简单吧。

    我们可以启动postman,请求count参数为1的话,查看业务数据库数据都正常。对应的库存减少了1,金额减少了100,订单成功插入。

    图片 图片 图片

    如果我们传入的count参数大于库存数,库存服务就会抛异常,那库存服务就会执行失败,这样订单服务,用户服务也会回滚。这样就起到了分布式事务作用。

    感觉到这里,小伙伴们是不是感觉seata的强大,这个就是seata推荐的AT模式。

    Feign降级坑

    在我们微服务使用中,一旦微服务产生异常,我们都会用到降级的功能;如在调用库存服务的时候引入sentinel降级,这个知识老顾之前就介绍过,小伙伴们可以查看之前的文章。

    图片 图片 图片
    spring:
      cloud:
        sentinel:
          transport:
            dashboard: 127.0.0.1:8080
    feign:
      sentinel:
        enabled: true
    

    这样对库存服务的降级处理是实现了,这也是正常的微服务的使用。

    但是这样的处理,seata就会失效;我们发现count参数大于库存时,库存服务报异常,但因为有降级处理,订单还是提交了订单数据,用户金额还是减少了。事务不起作用了。

    解决方式

    官方推荐的方法,就是利用aop方式,手动处理全局事务回滚,我们在库存服务中加入aop

    图片

    从上述代码中,我们用容易发现,如果执行的service中出现异常,就手动实现全局事务rollback。这样就解决了Feign的降级的问题。

    注意:上面的aop代码中,before、after方法中,可以结合自身的业务 本案例中库存服务,只在抛异常的时候做了处理

    总结

    seata的分布式事务使用起来是非常简单的,但是seata的使用会对现有项目中产生一些意外的错误,但是都可以得到相应的解决;需要小伙伴去实践。谢谢!!!

    相关文章

      网友评论

        本文标题:SpringCloud Alibaba之Seata入门以及踩坑(

        本文链接:https://www.haomeiwen.com/subject/vvnrgktx.html