Seata 介绍

Seata 简介

2019 年 1 月,阿里巴巴中间件团队发起了开源项目 Fescar(Fast & Easy Commit And Rollback),其愿景是让分布式事务的使用像本地事务的使用一样,简单和高效,并逐步解决开发者们遇到的分布式事务方面的所有难题。Fescar 开源后,蚂蚁金服加入 Fescar 社区参与共建,并在 Fescar 0.4.0 版本中贡献了 TCC 模式。为了打造更中立、更开放、生态更加丰富的分布式事务开源社区,经过社区核心成员的投票,决定对 Fescar 进行品牌升级,于 2019 年 5 月 开始更名为 Seata,意为:Simple Extensible Autonomous Transaction Architecture,是一套一站式分布式事务解决方案,为用户提供了 AT、TCC、SAGA 和 XA 事务模式。Seata 融合了阿里巴巴和蚂蚁金服在分布式事务技术上的积累,并沉淀了新零售、云计算和新金融等场景下丰富的实践经验,但要实现适用于所有的分布式事务场景的愿景,仍有很长的路要走。更多介绍可参考:Seata 项目、Seata 官方示例代码、Seata 官网、Seata 官方中文文档

Seata 演进历史

  • TXC:Taobao Transaction Constructor,阿里巴巴中间件团队自 2014
    年起启动该项目,以满足应用程序架构从单一服务变为微服务所导致的分布式事务问题
  • GTS:Global Transaction Service,2016 年 TXC 作为阿里中间件的产品,更名为 GTS 发布
  • FESCAR:2019 年开始基于 TXC/GTS 开源 FESCAR
  • SEATA:2019 年 5 月 FESCAR 更名为 SEATA

Seata 设计理念

Seata 的设计目标是对业务无侵入,因此从业务无侵入的 2PC 方案着手,在传统 2PC 的基础上演进。它把一个分布式事务理解成一个包含了若干分支事务的全局事务。全局事务的职责是协调其下管辖的分支事务达成一致,要么一起成功提交,要么一起失败回滚。此外,通常分支事务本身就是一个关系型数据库的本地事务。

在这里插入图片描述

Seata 的三大组件

  • TC:Transaction Coordinator 事务协调器,维护全局和分支事务的状态,负责协调并驱动全局事务的提交或回滚
  • TM:Transaction Manager 事务管理器,控制全局事务的边界,负责开启一个全局事务,并最终发起全局提交或全局回滚的决议
  • RM:Resource Manager 资源管理器,管理分支事务处理的资源,向 TC 注册分支事务,上报分支事务的状态,接受 TC的命令来提交或者回滚分支事务
    在这里插入图片描述

Seata 的执行流程

  • 1)A 服务的 TM 向 TC 申请开启一个全局事务,TC 就会创建一个全局事务并返回一个唯一的 XID
  • 2)A 服务的 RM 向 TC 注册分支事务,并将其纳入 XID 对应全局事务的管辖
  • 3)A 服务执行分支事务,向数据库执行操作
  • 4)A 服务开始远程调用 B 服务,此时 XID 会在微服务的调用链上传播
  • 5)B 服务的 RM 向 TC 注册分支事务,并将其纳入 XID 对应的全局事务的管辖
  • 6)B 服务执行分支事务,向数据库执行操作
  • 7)全局事务调用链处理完毕,TM 根据有无异常向 TC 发起全局事务的提交或者回滚
  • 8)TC 协调其管辖之下的所有分支事务,决定是否回滚

seata 实现的 2PC 与传统 2PC 的区别

  • 架构层次方面:传统 2PC 方案的 RM 实际上是在数据库层,RM 本质上就是数据库自身,通过 XA 协议实现,而 Seata 的RM 是以 Jar 包的形式作为中间件层部署在应用程序这一侧的
  • 两阶段提交方面:传统 2PC 无论第二阶段的决议是 Commit 还是 Rollback,事务性资源的锁都要保持到 Phase2完成才释放。而 Seata 的做法是在 Phase1 就将本地事务提交,这样就可以省去 Phase2 持锁的时间,整体提高了效率

Seata Server 安装

Seata 分 TC、TM 和 RM 三个角色,TC(Server 端)需要单独作为服务端部署,TM 和 RM(Client 端)由业务系统集成(如 Maven、Gradle)。

Seata Server 下载

  1. seata Server 的官方下载地址https://github.com/seata/seata/releases,直接下载已编译好的二进制包,然后解压即可使用,这里要注意的是下载的版本最好与你的项目中引入的seata依赖版本相同
  2. 还需要下载的是seata的源码代码,解压后需要使用下面的东西
    在这里插入图片描述

资源目录说明如下:

  • server:Server 端数据库脚本及各个容器配置
  • client:存放 Client 端的 SQL 脚本、参数配置
  • config-center:各个配置中心参数导入脚本,其中的 config.txt(包含 Server 和 Client,原名为
    nacos-config.txt) 为通用参数文件

Seata Server 配置

Seata Server(TC)的存储模式更改为 DB,即使用数据库来存储全局事务会话信息,同时自定义事务组的名称。这里演示使用的数据库为 MySQL,默认支持的数据库类型包括:MySQL、Oracle、PostgreSQL、H2、Oceanbase,其中 service.vgroupMapping 的详细介绍可以看自定义事务组的名称

这次模块搭建直接使用nacos作为注册和配置中心

  • 添加seata的数据库,在下载的源码内执行对应的sql创建一个库
    在这里插入图片描述

  • 添加配置文件到nacos,先修改config.text中的配置信息Seata 官方提供了将配置信息批量写入到各种主流配置中心的 Shell 脚本,存放路径是在 Seata 源码目录下的 script/config-center 目录(如下)

    script/config-center
    ├── apollo
    │   └── apollo-config.sh
    ├── config.txt
    ├── consul
    │   └── consul-config.sh
    ├── etcd3
    │   └── etcd3-config.sh
    ├── nacos
    │   ├── nacos-config.py
    │   └── nacos-config.sh
    ├── README.md
    └── zk
        └── zk-config.sh
    

    在这里插入图片描述

    transport.type=TCP
    transport.server=NIO
    transport.heartbeat=true
    transport.enableClientBatchSendRequest=false
    transport.threadFactory.bossThreadPrefix=NettyBoss
    transport.threadFactory.workerThreadPrefix=NettyServerNIOWorker
    transport.threadFactory.serverExecutorThreadPrefix=NettyServerBizHandler
    transport.threadFactory.shareBossWorker=false
    transport.threadFactory.clientSelectorThreadPrefix=NettyClientSelector
    transport.threadFactory.clientSelectorThreadSize=1
    transport.threadFactory.clientWorkerThreadPrefix=NettyClientWorkerThread
    transport.threadFactory.bossThreadSize=1
    transport.threadFactory.workerThreadSize=default
    transport.shutdown.wait=3
    service.vgroupMapping.tx_group_xiao7=default # 事务组是一定要相同的
    service.default.grouplist=127.0.0.1:8091
    service.enableDegrade=false
    service.disableGlobalTransaction=false
    client.rm.asyncCommitBufferLimit=10000
    client.rm.lock.retryInterval=10
    client.rm.lock.retryTimes=30
    client.rm.lock.retryPolicyBranchRollbackOnConflict=true
    client.rm.reportRetryCount=5
    client.rm.tableMetaCheckEnable=false
    client.rm.sqlParserType=druid
    client.rm.reportSuccessEnable=false
    client.rm.sagaBranchRegisterEnable=false
    client.tm.commitRetryCount=5
    client.tm.rollbackRetryCount=5
    client.tm.defaultGlobalTransactionTimeout=60000
    client.tm.degradeCheck=false
    client.tm.degradeCheckAllowTimes=10
    client.tm.degradeCheckPeriod=2000
    store.mode=db # 存储方式需要改成db
    store.file.dir=file_store/data
    store.file.maxBranchSessionSize=16384
    store.file.maxGlobalSessionSize=512
    store.file.fileWriteBufferCacheSize=16384
    store.file.flushDiskMode=async
    store.file.sessionReloadReadSize=100
    store.db.datasource=druid
    store.db.dbType=mysql
    store.db.driverClassName=com.mysql.jdbc.Driver
    store.db.url=jdbc:mysql://127.0.0.1:3306/seata?useUnicode=true
    store.db.user=root
    store.db.password=123456
    store.db.minConn=5
    store.db.maxConn=30
    store.db.globalTable=global_table
    store.db.branchTable=branch_table
    store.db.queryLimit=100
    store.db.lockTable=lock_table
    store.db.maxWait=5000
    store.redis.host=127.0.0.1
    store.redis.port=6379
    store.redis.maxConn=10
    store.redis.minConn=1
    store.redis.database=0
    store.redis.password=
    store.redis.queryLimit=100
    server.recovery.committingRetryPeriod=1000
    server.recovery.asynCommittingRetryPeriod=1000
    server.recovery.rollbackingRetryPeriod=1000
    server.recovery.timeoutRetryPeriod=1000
    server.maxCommitRetryTimeout=-1
    server.maxRollbackRetryTimeout=-1
    server.rollbackRetryTimeoutUnlockEnable=false
    client.undo.dataValidation=true
    client.undo.logSerialization=jackson
    client.undo.onlyCareUpdateColumns=true
    server.undo.logSaveDays=7
    server.undo.logDeletePeriod=86400000
    client.undo.logTable=undo_log
    client.log.exceptionRate=100
    transport.serialization=seata
    transport.compressor=none
    metrics.enabled=false
    metrics.registryType=compact
    metrics.exporterList=prometheus
    metrics.exporterPrometheusPort=9898
    
    

    然后使用脚本写入到到nacos

    nacos-config.sh -h 127.0.0.1 -p 8848 -t namespace -g group -u username -w password
    
  • 修改register.conf配置如下:

    registry {
      # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
      type = "nacos"
    
      nacos {
        application = "seata-server"
        serverAddr = "127.0.0.1:8848"
        group = "DEFAULT_GROUP"
        namespace = "9bde27a1-8cac-41a8-b09c-f49dc00f673e"
        cluster = "default"
        username = "nacos"
        password = "nacos"
      }
      file {
        name = "file.conf"
      }
    }
    
    config {
      # file、nacos 、apollo、zk、consul、etcd3
      type = "nacos"
    
      nacos {
        serverAddr = "127.0.0.1:8848"
        namespace = "9bde27a1-8cac-41a8-b09c-f49dc00f673e"
        group = "DEFAULT_GROUP"
        username = "nacos"
        password = "nacos"
      }
      file {
        name = "file.conf"
      }
    }
    
    
  • 最后启动服务

     sh seata-server.sh
    

Seata Server 的坑

default.grouplist 属性

Seata Serverfile.conf 配置文件中,有个 default.grouplist 配置,该配置的使用说明如下:

  • 1)只有在 registry.conf 中配置了 registry.type=file,即注册中心是 File 模式时,该配置才会起作用
  • 2)对应的值可以配置多个,配置多个就需要搭建 Seata Server 集群。由于默认并未提供本地文件的同步功能,所以在store.mode=file 模式下,这种集群方式的配置会报错;如果 Seata Server 搭建为集群,且store.mode=db,这样就可以通过 DB 来共享 TC(Seata Server) 集群间的数据
  • 3)当 registry.type=file 时,这个 default.grouplist 才会起作用,但是 File方式并不能提供一个注册中心的完整功能,比如健康检查机制,实例列表的更新剔出等,建议选择 Nacos 、Eureka、Redis、Zookeeper、Consul、Etcd3、Sofa 作为注册中心
  • 4)registry.type=fileconfig.type=file 的设计初衷,是让开发者在不依赖第三方注册中心或配置中心的前提下,可以通过 File 这种简单的直连快速验证 Seata服务,达到快速上手的目的

service.vgroup_mapping 属性

Seata Server <=1.0 的版本用的是 service.vgroup_mapping,但在新版本里改成了 service.vgroupMapping。若应用启动后无法连接 Seata Server,且抛出了以下异常信息,此时应该注意使用的是不是旧的 service.vgroup_mapping

no available service ‘null’ found, please make sure registry config correct

file.conf 配置文件中,service.vgroupMapping 支持配置多个:

service.vgroupMapping.user-service-group=default
service.vgroupMapping.order-service-group=default
service.vgroupMapping.account-service-group=default
service.vgroupMapping.storage-service-group=default
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐