Seata服务搭建及配合Nacos使用注册中心及配置中心

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第8天,点击查看活动详情

一、Seata 是什么

Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。AT模式是阿里首推的模式,阿里云上有商用版本的GTS(Global Transaction Service 全局事务服务)

官网:seata.io/zh-cn/index…

源码: github.com/seata/seata

官方Demo: github.com/seata/seata…

seata版本:v1.4.0

1-1、Seata的三大角色

在 Seata 的架构中,一共有三个角色:

TC (Transaction Coordinator) - 事务协调者

维护全局和分支事务的状态,驱动全局事务提交或回滚。

TM (Transaction Manager) - 事务管理器

定义全局事务的范围:开始全局事务、提交或回滚全局事务。

RM (Resource Manager) - 资源管理器

管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。

其中,TC 为单独部署的 Server 服务端,TM 和 RM 为嵌入到应用中的 Client 客户端。

在 Seata 中,一个分布式事务的生命周期如下:

0

1.TM 请求 TC 开启一个全局事务。TC 会生成一个 XID 作为该全局事务的编号。XID,会在微服务的调用链路中传播,保证将多个微服务的子事务关联在一起。

当一进入事务方法中就会生成XID , global_table 就是存储的全局事务信息 ,

2.RM 请求 TC 将本地事务注册为全局事务的分支事务,通过全局事务的 XID 进行关联。

当运行数据库操作方法,branch_table 存储事务参与者

3.TM 请求 TC 告诉 XID 对应的全局事务是进行提交还是回滚。

4.TC 驱动 RM 们将 XID 对应的自己的本地事务进行提交还是回滚。

0

1-2、设计思路

AT模式的核心是对业务无侵入,是一种改进后的两阶段提交,其设计思路如图

第一阶段

业务数据和回滚日志记录在同一个本地事务中提交,释放本地锁和连接资源。核心在于对业务sql进行解析,转换成undolog,并同时入库,这是怎么做的呢?先抛出一个概念DataSourceProxy代理数据源,通过名字大家大概也能基本猜到是什么个操作,后面做具体分析

参考官方文档: seata.io/zh-cn/docs/…

0

第二阶段 分布式事务操作成功,则TC通知RM异步删除undolog image.png

分布式事务操作失败,TM向TC发送回滚请求,RM 收到协调器TC发来的回滚请求,通过 XID 和 Branch ID 找到相应的回滚日志记录,通过回滚记录生成反向的更新 SQL 并执行,以完成分支的回滚。

image.png

整体执行流程

0

1-3、设计亮点

相比与其它分布式事务框架,Seata架构的亮点主要有几个:

  1. 应用层基于SQL解析实现了自动补偿,从而最大程度的降低业务侵入性;
  2. 将分布式事务中TC(事务协调者)独立部署,负责事务的注册、回滚;
  3. 通过全局锁实现了写隔离与读隔离。

1-4、存在的问题

性能损耗

一条Update的SQL,则需要全局事务xid获取(与TC通讯)、before image(解析SQL,查询一次数据库)、after image(查询一次数据库)、insert undo log(写一次数据库)、before commit(与TC通讯,判断锁冲突),这些操作都需要一次远程通讯RPC,而且是同步的。另外undo log写入时blob字段的插入性能也是不高的。每条写SQL都会增加这么多开销,粗略估计会增加5倍响应时间。

性价比

为了进行自动补偿,需要对所有交易生成前后镜像并持久化,可是在实际业务场景下,这个是成功率有多高,或者说分布式事务失败需要回滚的有多少比率?按照二八原则预估,为了20%的交易回滚,需要将80%的成功交易的响应时间增加5倍,这样的代价相比于让应用开发一个补偿交易是否是值得?

全局锁

热点数据

相比XA,Seata 虽然在一阶段成功后会释放数据库锁,但一阶段在commit前全局锁的判定也拉长了对数据锁的占有时间,这个开销比XA的prepare低多少需要根据实际业务场景进行测试。全局锁的引入实现了隔离性,但带来的问题就是阻塞,降低并发性,尤其是热点数据,这个问题会更加严重。

回滚锁释放时间

Seata在回滚时,需要先删除各节点的undo log,然后才能释放TC内存中的锁,所以如果第二阶段是回滚,释放锁的时间会更长。

死锁问题

Seata的引入全局锁会额外增加死锁的风险,但如果出现死锁,会不断进行重试,最后靠等待全局锁超时,这种方式并不优雅,也延长了对数据库锁的占有时间。

二、Seata快速开始

2-1、Seata Server(TC)环境搭建

可以参考一下官网 seata.io/zh-cn/docs/…

我这边Spring Cloud Alibaba的版本问2.2.6.RELEASE,因此Seata的版本选择1.3.0 image.png

2-1-1、下载安装包

github.com/seata/seata…

image.png

2-1-2、Server端存储模式(store.mode)支持三种

安装服务之前,首先要知道Seata有三种数据存储方案,分别为:

1、file:(默认)单机模式,全局事务会话信息内存中读写并持久化本地文件root.data,性能较高(默认)
2、db:(5.7+)高可用模式,全局事务会话信息通过db共享,相应性能差些, 但是如果使用 S e a t a 集群,还是需要使用 D B 方案的,这样可以保证数据一致性 \color{red}{但是如果使用Seata集群,还是需要使用DB方案的,这样可以保证数据一致性}
3、redis:Seata-Server 1.3及以上版本支持,性能较高,存在事务信息丢失风险,请提前配置适合当前场景的redis持久化配置

下面使用DB的方式来进行安装

2-1-3、安装

2-1-3-1、将文件复制到/usr/local下,进行解压

cd /usr/local/
tar -zxvf seata-server-1.3.0.tar.gz 

2-1-3-2、修改存储方式为DB

vim ./seata/conf/file.conf

1、将mode改为db

image.png

2、修改数据库连接

image.png

3、创建数据库

首先创建seata_server数据

image.png

4、创建数据库表

去seata官网 seata.io/zh-cn/docs/…

找到资源目录下的点击查看

image.png

进入目录,拷贝MySQL建表语句

image.png

执行建表语句,生成表

image.png

2-1-3-3、修改注册中心和配置中心

seata是阿里系,那么注册中心和配置中心就使用nacos了

2-1-3-3-1、修改注册中心

因为服务参与者和seata的服务协调者需要通信,因此需要使用到注册中心,默认使用file类型

1、打开配置文件

vim conf/registry.conf

修改注册中心类型为nacos,和nacos配置信息,需要注意的是naspace如果不指定默认public,如果指定一定要现在nacos创建好命名空间,然后拷贝dataId到namespace这个地方,不是拷贝namespace名称

image.png

2-1-3-3-2、修改配置中心

如果不修改配置中心,就默认使用file进行存储配置信息,这样在后期动态扩展、修改配置的情况下就比较麻烦了。

vim conf/registry.conf

修改配置中心类型为nacos,和nacos配置信息,其中namespace建议改为自定义不要用public(后面在配置中心使用的时候,会把所有配置挨个注册得到配置中心),我这边使用seata(dataId:b2650ce0-5da2-4e1c-95ac-d3a6fb26d01f)

image.png

2-1-3-4、修改配置文件信息

默认的配置,官方也给出了相关信息,建议将script下载拷贝到安装seata的目录下面,后面执行注册的时候也会用到,复制进去之后,修改默认配置文件

2-1-3-4-1、修改数据存储方式和数据库信息

打开默认配置文件

vim script/config-center/config.txt

image.png

2-1-3-4-2、事务分组

比如我们要给seata配置一个高可用的集群方案:
北京:seata集群
广州:seata集群
上海:seata集群

通过以上部署,如果北京机房突然停电,或者遇到其他情况无法提供服务,就可以将调用北京的集群服务,切换到广州或者上海,非常简单就完成了服务的切换,下面来配置一下

依然打开默认配置文件

vim script/config-center/config.txt

image.png

如上配置即为配置事务分组的,其中my_test_tx_group即为分组名称,default需要跟客户端和registry.conf中registry中的cluster保持一致,如下:

image.png

我这边先改为beijing

image.png

2-1-3-5、将配置同步到Nacos

2-1-3-5-1、创建seata命名空间

首先去nacos创建一个命名空间:seata,创建完成之后复制这个ID image.png

2-1-3-5-2、执行同步

然后给nacos注册文件赋执行权限

chmod +x ./script/config-center/nacos/nacos-config.sh

执行命令

/nacos-config.sh -h localhost -p 8851 -g SEATA_GROUP -t b2650ce0-5da2-4e1c-95ac-d3a6fb26d01f -u nacos -w nacos

参数说明:

-h: host,默认值 localhost

-p: port,默认值 8848

-g: 配置分组,默认值为 'SEATA_GROUP'

-t: 命名空间的ID

-u: nacos账号

-w: nacos密码

执行之后找的config.txt路径不对,可以修改一些nacos-config.sh里面的路径,也可以将config.txt拷贝到/usr/local下面,我就直接拷贝文件了 image.png

再次执行,就可以执行成功了,每行显示都是successfully

image.png

2-1-3-5-3、查看nacos配置

可以看到相关配置信息已经注册到了nacos image.png

2-1-4、启动服务

  • 源码启动: 执行server模块下io.seata.server.Server.java的main方法
  • 命令启动: bin/seata-server.sh -h 127.0.0.1 -p 8091 -m db -n 1 -e test

image.png

启动Seata Server,我这边启动两个

./bin/seata-server.sh -p 8091 -n 1
./bin/seata-server.sh -p 8092 -n 2

如果启动失败,需要看下默认的 J V M 配置堆区的内存(默认 2 G ),虚拟机适当改小一点 \color{red}{如果启动失败,需要看下默认的JVM配置堆区的内存(默认2G),虚拟机适当改小一点}

服务启动成功 image.png

在Nacos注册中心可以看到seata-server注册成功,集群数量为1,实例数为2。 image.png

猜你喜欢

转载自juejin.im/post/7127444807022018597