目录
(五)AT事务——Automatic Transaction
一、事务
严格来说事务应该具备原子性、一致性、隔离性和持久性,简称 ACID。
- 原子性(Atomicity):一个事务内的所有操作不可被打断,要么全部完成,要么不做任何操作,如果在执行的过程中发生了错误,要回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过。
- 一致性(Consistency):也叫数据一致性,比如你账上有400,我账上有100,你给我打200块,此时你账上的钱应该是200,我账上的钱应该是300,不会存在我账上钱加了,你账上钱没扣。
- 隔离性(Isolation),指的是多个事务并发执行的时候不会互相干扰,即一个事务内部的数据对于其他事务来说是隔离的。
- 持久性(Durability),指的是一个事务完成了之后数据就被永远保存下来。
二、分布式事务
在分布式系统中,很多操作都是跨数据库,由多个本地事务组合而成,这种情况根本无法满足:ACID。比如:
- 从浏览器发送一个下单请求,到聚合服务
- 聚合服务,先调用订单服务,再调用库存服务,这两个服务分别操作不同的库
- 如果下单成功,但是扣减库存失败,但这时订单数据库已经保存,无法回滚,就会产生数据安全问题。
三、分布式事务问题解决方案
(一)两阶段提交——2PC
两阶段提交是一种协调型的分布式事务解决方案,它由一个协调者和多个参与者组成。
事务管理器:也叫事务协调者(TM),资源管理器:就是参与者(RM)
第一阶段
- 订单服务和库存服务分别执行sql,但是不提交
第二阶段
- 事务管理器拿到sql执行结果
- 都成功,发送commit命令,两个服务同时提交事务
- 有失败,发送rollback命令,两个服务同时回滚
缺点:
- 性能问题:订单服务成功,但是库存执行时间比较长,这时订单服务一直没有提交事务,会影响其他人的读写。
- 数据一致性:
事务管理器向订单服务发送commit命令后宕机,库存服务无法提交事务。
事务的参与者,有的提交成功,有的提交失败。
(二)三阶段提交——3PC
3PC把2PC的第一阶段,细分成了CanCommit和PreCommit。新增的CanCommit是一个询问阶段,让参与者执行sql前,根据条件判断该事务是否能顺利完成。比如:扣减库存,先判断库存够不够。
优点:
- 3PC解决了2PC的单点问题:如果协调者宕机,参与者没有收到commit的消息,3PC默认将事务提交,而不是回滚事务或者继续等待
缺点:
- 性能较差:多了一个询问阶段,所以性能反而会更差,如果是需要回滚的场景中,3PC的性能通常要好一些。
- 没有解决数据一致性问题。
(三)TCC——Try-Confirm-Cancel
分为3个阶段
- Try 阶段:对业务系统做检测及资源预留。
- Confirm 阶段:对业务系统做确认提交,Try成功,执行 Confirm 时,默认 Confirm阶段是不会出错的。即:只要Try成功,Confirm一定成功。
- Cancel 阶段:如果任何一个在Try阶段失败或在Confirm阶段执行发生异常,系统会进入Cancel阶段。在这个阶段,之前预留的资源将被释放,回滚未完成的操作,以实现事务的取消或者撤销。Cancel阶段的操作也应该是幂等的。
假设有两个用户A和B,用户A要向用户B进行转账操作。下面是TCC模型在转账场景中的应用:
- Try阶段:在这个阶段,系统会检查用户A的账户余额是否充足,并将转账状态设置为"待确认"。同时,系统会冻结用户A账户中对应转账金额。
- Confirm阶段:如果Try阶段全部成功完成,系统会进入Confirm阶段。在这个阶段,系统会将转账状态更新为"已确认",并从用户A的账户中扣除转账金额。同时,系统会将相应的转账金额添加到用户B的账户中。
- Cancel阶段:如果在Try阶段或Confirm阶段出现任何错误,系统会进入Cancel阶段。在这个阶段,系统会释放之前冻结的转账金额,恢复用户A账户中的余额。
缺点:
太麻烦,一个操作需要写3个方法,业务侵入性高,开发成本高。
(四)本地消息表——Local Message Table
事务发起方,建一个消息表,在存储业务数据的时,也往消息表中记录,这两个操作是在一个事务里提交,后台会扫描消息表,之后发送MQ消息到消费方。如果消息发送失败,会进行重试发送。消费方,拿到消息后,处理自己的业务逻辑。
处理成功:
- 发送一个消息给事务发起方,修改消息表中的消息状态。
处理失败:
- 重试;
- 如果是业务上面的失败,可以给事务发起方发送一个消息,通知进行回滚操作。
(五)AT事务——Automatic Transaction
AT 事务 是 Seata 框架中的一种分布式事务模式,全称为 Automatic Transaction。它是一种无侵入式的分布式事务解决方案,通过对业务代码的自动代理,实现分布式事务的管理。AT 事务的核心思想是通过对 SQL 的解析和回滚日志的生成,自动完成事务的提交和回滚。
阿里的开源 seata,和商业版的GTS,一般使用这种方式,是2PC的优化,基本流程如下:
第一阶段:执行SQL时,自动拦截所有的SQL,保存SQL对数据修改前后的快照,为了回滚使用。
第二阶段:所有参与者的事务都成功,只需清理每个数据源中对应的日志数据。
第三阶段:回滚,如果有参与者失败,就要根据日志数据进行回滚。
好处:分布式事务中所涉及的每一个数据源都可以单独提交,然后立刻释放资源,相比两阶段提交,极大的提升了系统的吞吐量。
四、Seata介绍
在微服务架构中,一次业务操作需要跨多个数据库或者多个系统远程调用,就会产生分布式事务问题。
Seata是阿里提供给的分布式事务解决方案
官网地址:Apache Seata
用户文档:Seata 是什么? | Apache Seata
git地址:https://github.com/seata/seata
五、Seata安装配置
1.安装JDK8并关闭防火墙
步骤略
export JAVA_HOME=/home/soft/jdk1.8.0_202
# 如果是 JDK11 不需要 CLASSPATH 这个配置
export CLASSPATH=.:${JAVA_HOME}/jre/lib/rt.jar:${JAVA_HOME}/lib/dt.jar:${JAVA_HOME}/lib/tools.jar
export PATH=$PATH:${JAVA_HOME}/bin
2. 下载Seata1.5.2
下载地址:https://seata.apache.org/zh-cn/release-history/seata-server
github地址:https://github.com/apache/incubator-seata/releases/tag/v1.5.2
下载后,上传 seata-server-1.5.2.tar.gz 到 /home/soft 目录
执行:tar -zxvf seata-server-1.5.2.tar.gz,解压:
3.注册nacos
把seata注册到 nacos中,作为一个服务,所以先操作 nacos
在 seata 空间,增加一个 seata-server 的配置,这些配置都是 seata 使用
至于配置内容,从 seata 的源码包中获取
在源码文件夹的 script\config-center 目录下,有个config.txt
但是需要修改其中几项,比如:
注意:上图中的数据库连接是mysql8版本,不同的mysql版本jdbc连接和driverClass不同,自行选择。
修改 seata 中的 application.yml
从24行开始,修改其中的部分配置,比如:
seata:
config:
# support: nacos, consul, apollo, zk, etcd3
type: nacos # 表示从nacos中获取配置
nacos:
server-addr: 192.168.157.102:8848
namespace: seata # 注意:这里是namespace的id
group: SEATA_GROUP
username: nacos
password: nacos
data-id: seata-server
registry:
# support: nacos, eureka, redis, zk, consul, etcd3, sofa
type: nacos # 表示把seata作为一个服务注册到nacos上
nacos:
application: seata-server
server-addr: 192.168.157.102:8848
group: SEATA_GROUP
namespace: seata
cluster: default
username: nacos
password: nacos
# stor#e:
# support: file 、 db 、 redis
# mode: filev
解释:
- server-addr:nacos地址
- namespace:命名空间,默认是public,设置为 seata
- group:服务分组,nacos上注册的服务可以分组
- username:nacos用户名
- password:nacos密码
- application:服务名,把seata当做一个服务注册到nacos上
- cluster:设置为default
4.初始化seata数据库
配置了数据库链接,所以自己创建 seata 数据库,选择utf8编码就行
执行sql:找到下载的seata源码,在下面路径中可以找到sql
执行结果:
5.设置启动内存
默认 seata 启动时占用内存比较大,可以通过它的启动文件进行设置
在下面目录中找到:seata-server.sh
定位到129行,修改结果如下:
6.启动
注意:需要先启动nacos
在bin目录下面中找到:seata-server.sh
执行:./seata-server.sh -h 本机IP地址
[root@localhost bin]# ./seata-server.sh -h 192.168.157.103
# 查看启动日志
[root@localhost bin]# tail -f ../logs/start.out
nacos中查看
浏览器访问:http://192.168.157.103:7091/#/login
用户名、密码 都是:seata