Seata—分布式事务介绍
事务ACID
Seata就是解决这两种分布式事务的场景的

Seata—什么是Seata
Sea是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务,Seata将为用户提供了AT、TCC、SAGA和XA事务模式,为用户打造一站式的分布式解决方案。AT模式是阿里首推的模式,阿里云上有商用版本的GTS(Global Transaction Service 全局事务服务)
Seata—二阶段提交协议
1.seata阿里分布式事务框架
2.消息队列
3.saga
4.XA
他们有一个共同点,都是"两阶段(2PC)"。"两阶段"是指完成整个分布式事务,划分成两个步骤完成。实际上,这四种常见的分布式事务廨决方案,分别对应着分布式事务的四种模式: AT、TCC、Saga、XA;
2PC两阶段提交协议(Two-Phase Commit):
顾名思义分为两个阶段 Prepare 和 Commit
Prepare : 提交事务请求
基本流程如下图:

1.询问 协调者向所有参与者发送事务请求,询问是否可执行事务操作,然后等待各个参与者的响应。
⒉执行 各个参与者接收到协调者事务请求后,执行事务操作(例如更新一个关系型数据库表中的记录),并将Undo和Redo信息记录事务日志中。
3 响应 如果参与者成功执行了事务并写入Undo和Redo信息,则向协调者返回YES响应,否则返回NO响应。当然,参与者可能宕机,从而不会返回响应
Commit: 执行事务提交
基本流程如下图:

- commit 请求协调者向所有参与者发送Commit 请求。
- 事务提交参与者收到Commit 请求后,执行事务提交,提交完成后释放事务执行期占用的所有资源。
- 反馈结果参与者执行事务提交后向协调者发送Ack响应。
- 完成事务接收到所有参与者的Ack 响应后,完成事务提交。
中断事务
在执行Prepare步骤过程中,如果某些参与者执行事务失败、宕机或与协调者之间的网络中断,那么协调者就无法收到所有参与者的YES响应,或者某个参与者返回了No响应.此时,协调者就会进入回退流程,对事务进行回退。流程如下图红色部分(将Commit 请求替换为红色的Rollback 请求):

- rollback请求协调者向所有参与者发送Rollback 请求。
- 事务回滚参与者收到Rollback 后,使用Prepare阶段的Undo日志执行事务回滚,完成后释放事务执行期占用的所有资源。
- 反馈结果参与者执行事务回滚后向协调者发送Ack 响应。
- 中断事务接收到所有参与者的Ack 响应后,完成事务中断。

2PC的问题
1.同步阻塞
2.单点故障
3.数据不一致
4.环境可靠性依赖性
Seata—分布式解决方案:AT模式
AT模式 : auto transcation(主推)
AT模式是—种无侵入的分布式事务解决方案,
阿里seata框架,实现了该模式。
在AT模式下,用户只需关注自己的"业务SQL",用户的“业务SQL"作为一阶段,Seata框架会自动生成事务的二阶段提交和回滚操作。

AT模式如何做到对业务的无侵入∶
- 一阶段 :
在一阶段,Seata 会拦截“业务SQL”,首先解析SQL语义,找到“业务SQL"要更新的业务数据,在业务数据被更新前,将其保存成"before image,然后执行业务SQL"更新业务数据,在业务数据更新之后,再将其保存成"after image’,最后生成行锁。以上操作全部在一个数据库事务内完成,这样保证了一阶段操作的原子性。


- 二阶段提交:
二阶段如果是提交的话,因为"业务SQL"在一阶段已经提交至数据库,所以Seata框架只需将一阶段保存的快照数据和行锁删掉,完成数据清理即可.

- 二阶段回滚:
二阶段如果是回滚的话,Seata就需要回滚一阶段已经执行的M业务SQL",还原业务数据。回滚方式便是用"before image"还原业务数据;但在还原前要首先要校验脏写,对比"数据库当前业务数据"和"after image,如果两份数据完全一致就说明没有脏写,可以还原业务数据,如果不一致就说明有脏写,出现脏写就需要转人工处理。

Seata—分布式解决方案:TCC模式
tcc == try confirm cancel
TCC模式需要用户根据自己的业务场景实现Ty、Confim和Cancel三个操作;事务发起方在一阶段执行Try 方式,在二阶段提交执行Confirm方法,二阶段回滚执行Cancel方法。
优点 : 在整个过程基本没有锁,性能更强
缺点 : 侵入性比较强,并且得自己实现相关事务控制逻辑

可靠消息最终一致性方案

Seata—Seate的AT模式原理
在Seata的架构中,一共有三个角色:
Tc (Transaction Coordinator)-事务协调者
维护全局和分支事务的状态,驱动全局事务提交或回滚。
TM(Transaction Manager)-事务管理器
定义全局事务的范围:开始全局事务、提交或回滚全局事务。
RM(Resource Manager)-资源管理器
管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚。
其中,TC为单独部署的Server服务端,TM和RM为嵌入到应用中的 Client客户端。
第一阶段

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

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

Seata—服务搭建—db数据源
Seata Server(TC)环境搭建
下载地址 https://github.com/seata/seata/releases
2.2.5对应1.3.0 下载1.3.0版本 后解压
Server端存储模式(store.mode)支持三种:
- file:(默认)单机模式,全局事务会话信息内存中读写并持久化本地文件root.data,性能较高(默认)
- db:高可用模式 , 全局事务会话信息通过db共享,相应性能差些
- redis: Seata-Server 1.3及以上版本支持,性能较高,存在事务信息丢失风险,.请提前配置适合当前场景的redis持久化配置
1.打开conf/file.conf
第3-5行中 修改
mode="file" 修改成 mode="db"

修改数据源

2.创建数据库seata_server
数据库语句 https://github.com/seata/seata/tree/1.4.0/script/server/db
运行mysql.sql后有这三张表

Seata—服务搭建—nacos
db+Nacos得方式部署高可用集群模式
先启动 Nacos
1.修改seata/conf/registry.conf
type = 'file 修改成 'type = 'nacos'
# 除了nacos 下面的配置去掉

修改下面的config(也是在seata/conf/registry.conf里面)

修改script/config-center/config.txt
store.mode改成db 下面选中删掉

再修改下面的数据源

事务分组:异地机房停电容错机制
my_test_tx_group 可以自定义 比如:(guangzhou,shanghai…),对应的client也要去设置
这边的default 必须要等于 registry.conf cluster = “default”

运行script/config-center/nacos 下的 nacos-config.sh 就可以将config.txt注册到nacos中心因为是本机127.0.0.1所以可以直接注册
运行结束后nacos配置列表多了很多规则
nacos中效果

自定义 ---- shell(git bash):
sh $[SEATAPAR)/script/config-certer/nacos/nacos-config.sh -h localhost -p 8848 -g SEATA_GROUP -t 5a3c7d6c-f497-4d68-71a-2e5e3340b3ca
-h: host,默认值localhost
-p: port,默认值8848
-g: 配置分组,默认值为’SEATA_GROUP’
-t: 租户信息,对应 Nacos的命名空间ID字段,默认值为空"
然后就可以运行 seata/bin/seata-server.bat了 端口是8091
发现报错
我们缺少logs文件夹下的seata_gc.log
我们在bin目录的同级目录下创建logs目录,在logs目录下创建seata_gc.log,需要注意的一点是要把seata_gc.log文件的其他后缀都去掉,只要seata_gc.log
又发现问题 数据库driverClassName 要用com.mysql.cj.jdbc.Driver
(我的数据库是8.0)
然后保存启动seata
启动成功 nacos中查看服务列表多了一个服务

(linux集群)更改端口
bin/seata-server.sh -p 8092 -n 1
bin/seata-server.sh -p 8093 -n 2
bin/seata-server.sh -p 8094 -n 3
Seata—分布式事务代码搭建
声明式事务实现 (@GlobalTransactional)
基础环境

order-seata模块
controller层

service层

思考 用@Transactional注解处理 如果抛出异常会怎样
答 insert方法回滚 但远程服务就不会回滚
stock-seata模块
controller层

service层

访问 /order/add 页面显示报错
现象 order没有插入 但stock减库存了
本地@Transactional注解是没有办法解决分布式事务的场景
Seata—Client搭建
1.添加依赖(stock-seata模块和order-seata模块)
<!--seata的依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
2.各(两个数据库)服务对应数据库中添加undo_log表
create table `undo_log`(
`id` bigint(20) not null auto_increment,
`brand_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,
primary key(`id`),
unique key `ux_undo_log` (`xid`,`brand_id`)
)engine=InnoDB auto_increment=1 default charset = utf8;
3.配置文件(两个模块)
#而皮质事务分组
spring:
cloud:
alibaba:
seata:
tx-service-group: my_test_tx_group #对应配置文件中的名字
seata:
registry:
#配置seata的注册中心,告诉seata client怎么去访问seata server
type: nacos
nacos:
server-addr: 127.0.0.1:8848 #seata server 所在的nacos服务地址
application: seata-server # seata server 的服务名,默认就是seata-server,没有改可以不配
username: nacos
password: nacos
group: SEATA_GROUP # seata server 所在的组,默认就是SEATA_GROUP,没有改可以不配
config:
type: nacos
nacos:
server-addr: 127.0.0.1:8848
username: nacos
password: nacos
group: SEATA_GROUP

4.更改注解
将之前的 @Transactional 注解改成 @GlobalTransactional 注解
5.测试访问
访问 /order/add 页面显示报错
现象 order没有插入 stock减库也没有减
说明都回滚了 成功!
思考 配置中心那么多有什么用
就是为了读取我们之前的配置 db、数据库这种我们之前自定义的配置
Seata—运行原理总结

1.TM请求TC开启一个全局事务。 TC会生成一个XID作为该全局事务的编号。 XID,会在微服务的调用链路中传播,保证将多个微服务的子事务关联在一起.
(当一进入事务方法中就会生成XID global_table)
2.RM请求TC将本地事务注册为全局事务的分支事务,通过全局事务的XID进行关联。
(当运行数据库操作方法 branch_table 存储事务参与者)
3.TM请求TC告诉XID对应的全局事务是进行提交还是回滚。
4.TC驱动RM们将XID对应的自己的本地事务进行提交还是回滚。
在插入订单那打个断点 发现global_table生成一条数据,就是全局事务的信息(包括XID)
每一个@GlobalTransactional 注解在都会在global_table生成一条全局事务的信息

branch_table 存储事务参与者
lock_table 锁表
1610

被折叠的 条评论
为什么被折叠?



