• 分布式事务 —— SpringCloud Alibaba Seata


    Seata 简介

    传统的单体应用中,业务操作使用同一条连接操作不同的数据表,一旦出现异常就可以整体回滚。随着公司的快速发展、业务需求的变化,单体应用被拆分成微服务应用,原来的单体应用被拆分成多个独立的微服务,分别使用独立的数据源,业务操作需要调用三个服务来完成。此时每个服务内部的数据一致性由本地事务来保证,但是全局的数据一致性问题无法保证。在微服务架构中,一次业务请求需要操作多个数据源或需要进行远程调用,就会产生分布式事务问题。

    Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务,Seata 为用户提供 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。AT 模式是 Seata 默认的工作模式,该模式是 XA 协议的演变。

    关于分布式事务的知识可以参考:https://zhuanlan.zhihu.com/p/263555694

    Seata 服务端

    通过 https://github.com/seata/seata/releases 地址下载 Seata 安装包,本文使用的 Seata 版本是 seata-server-1.7.1

    解压 seata-server-1.7.1 安装包,修改 conf/application.conf 文件

    yaml
    server:
      port: 7091
    
    spring:
      application:
        name: seata-server
    
    logging:
      config: classpath:logback-spring.xml
      file:
        path: D:\seata-server-1.7.1\logs\seata
      extend:
        logstash-appender:
          destination: 127.0.0.1:4560
        kafka-appender:
          bootstrap-servers: 127.0.0.1:9092
          topic: logback_to_logstash
    
    console:
      user:
        username: seata
        password: seata
    seata:
      config:
        # 使用nacos作为配置中心,seata将从nacos获取配置
        type: nacos
        nacos:
          server-addr: 127.0.0.1:8848
          namespace: 0178e474-2cfb-47c3-bded-da7cfa260f99
          group: springcloud-project
          data-id: seata-server.properties
      registry:
        # 使用nacos作为注册中心,seata将自身服务注册到nacos
        type: nacos
        nacos:
          server-addr: 127.0.0.1:8848
          namespace: 0178e474-2cfb-47c3-bded-da7cfa260f99
          group: springcloud-project
          application: seata-server
          cluster: default
      store:
        # 存储模式:
        # file模式为单机模式,全局事务会话信息内存中读写并持久化本地文件 rootdata,性能较高
        # db模式为高可用模式,全局事务会话信息通过db共享,相应性能会差
        # redis模式性能较高,存在事务信息丢失风险,需要提前配置适合当前场景的redis持久化配置
        mode: file
    #  server:
    #    service-port: 8091 #If not configured, the default is '${server.port} + 1000'
      security:
        secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
        tokenValidityInMilliseconds: 1800000
        ignore:
          urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.jpeg,/**/*.ico,/api/v1/auth/login
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    在 Nacos 控制台创建配置文件 seata-server.properties,注意分组和命名空间要与上述配置保持一致

    具体配置项是从 script/config-center/config.txt 粘贴修改而来,这里只使用对我们有用的配置,主要是数据库配置信息

    properties
    #Transaction storage configuration, only for the server.
    store.mode=db
    store.lock.mode=db
    store.session.mode=db
    
    #These configurations are required if the `store mode` is `db`.
    store.db.datasource=druid
    store.db.dbType=mysql
    store.db.driverClassName=com.mysql.cj.jdbc.Driver
    store.db.url=jdbc:mysql://127.0.0.1:3306/test_db?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useAffectedRows=true
    store.db.user=root
    store.db.password=123
    store.db.minConn=5
    store.db.maxConn=30
    store.db.globalTable=global_table
    store.db.branchTable=branch_table
    store.db.distributedLockTable=distributed_lock
    store.db.queryLimit=100
    store.db.lockTable=lock_table
    store.db.maxWait=5000
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在上面配置的数据库内,执行 script/server/db 目录下的 sql 脚本,创建服务端所需的表

    完成以后,即可进入 bin 目录使用脚本启动 Seata

    Seata 客户端

    为客户端微服务添加依赖

    <dependency>
        <groupId>com.alibaba.cloudgroupId>
        <artifactId>spring-cloud-starter-alibaba-seataartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4

    配置文件添加如下配置

    seata:
      enabled: true
      tx-service-group: test-seata-group # 自定义事务组名称,需要与下面service.vgroup-mapping中的一个映射保持一致
      service:
        vgroup-mapping:
          test-seata-group: default
      registry:
        type: nacos
        nacos:
          server-addr: 127.0.0.1:8847/nacos
          namespace: 0178e474-2cfb-47c3-bded-da7cfa260f99
          group: springcloud-project
          application: seata-server
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    Seata 默认使用 AT 模式,该模式需求每个客户端库内都存在一张 undo_log 表,用于回滚事务时临时记录数据

    CREATE TABLE `undo_log` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT,
      `branch_id` bigint(20) NOT NULL,
      `xid` varchar(100) NOT NULL,
      `context` varchar(128) NOT NULL,
      `rollback_info` longblob NOT NULL,
      `log_status` int(11) NOT NULL,
      `log_created` datetime NOT NULL,
      `log_modified` datetime NOT NULL,
      `ext` varchar(100) DEFAULT NULL,
      PRIMARY KEY (`id`),
      UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在需要使用分布式事务的方法上添加注解 @GlobalTransactional,当方法内发生异常时,就可以带动所调用微服务进行回滚

    @GlobalTransactional
    public void create(Order order) {
    
        log.info("下单开始");
        orderDao.create(order);
        log.info("下单结束");
    
        log.info("开始扣减余额");
        server02FeignClient.accountIncrUsed(order.getUserId(), order.getMoney());
        log.info("扣减余额结束");
    
        log.info("开始扣减库存");
        server03FeignClient.storageIncrUsed(order.getProductId(), order.getCount());
        log.info("扣减库存结束");
    
        log.info("开始修改订单状态");
        orderDao.updateStatus(1, order.getId());
        log.info("修改订单状态结束");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    配置完成,启动服务,即可开始测试

  • 相关阅读:
    部署MongoDB复制集群(最全)
    基于Java语言实现模拟银行存取款业务系统
    第二篇------Virtual I/O Device (VIRTIO) Version 1.1
    What makes training multi-modal classification networks hard?
    React18中各种Hooks用法总结( 内附案例讲解)
    优酷 Android 包瘦身治理思路全解
    Django重定向类HttpResponseRedirect、HttpResponsePermanentRedirect和重定向函数redirect
    快速从0-1完成聊天室开发——环信ChatroomUIKit功能详解
    【数据结构与算法系列5】螺旋矩阵II (C++ & Python)
    QT DAY2
  • 原文地址:https://blog.csdn.net/weixin_44816664/article/details/133625442