- 分布式事务介绍
- 什么是Seata
- 二阶段提交协议
- 分布式解决方案:AT模式
- 分布式解决方案:TCC模式
- 可靠消息最终一致性方案
- Seata的AT模式原理
- Seata服务搭建-db数据源
- transaction log store, only used in seata-server
- store mode: file、db、redis
- 修改这里的模式为数据库模式(db)
- file store property
- store location dir
- branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions
- globe session size , if exceeded throws exceptions
- file buffer size , if exceeded allocate new buffer
- when recover batch read size
- async, sync
- 新旧版本的数据库所用的驱动是不同的
分布式事务介绍
事务的四个属性(ACID):原子性、一致性、隔离型、持久性
本地事务:
@Transational
:大多数场景下,我们的应用都只需要操作单一的数据库,这种情况下的事务称之为本地事务。本地事务的ACID特性是数据库直接提供支持的。
分布式事务:
什么是Seata
是一款开源的分布式事务解决发噶,致力于提高性能和简单易用的分布式事务服务。Seata将为用户提供了AT、TCC、SAGA和XA事务模式,为用户打造一站式的分布式解决方案。AT模式是阿里首推的模式。
官网:http://seata.io/zh-cn/index.html
源码:https://github.com/seata/seata
官方demo:https://github.com/seata/seata-samples
Seata的三大角色
- TC (Transaction Coordinator) - 事务协调者 维护全局和分支事务的状态,驱动全局事务提交或回滚
- TM (Transaction Manager) - 事务管理器 定义全局事务的范围:开始全局事务、提交或回滚全局事务
- RM (Resource Manager) - 资源管理器管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚
其中,TC为单独部署的Server服务端,TM和RM为嵌入到应用中的Client客户端。
二阶段提交协议
2PC两阶段提交协议,顾名思义,分为两个阶段:Prepare和commit
prepare:提交事务请求,基本流程如下:
过程:
- 询问 协调者向所有参与者发送事务请求,询问是否可执行事务操作,然后等待各个参与者的响应
- 执行 各个参与者接收到协调者事务请求后,执行事务操作,并将Undo和Redo的信息记录
- 响应 如果参与者成功执行了事务并写入Undo和Redo信息,则向协调者返回YES响应,否则返回NO响应,参与者也可能宕机,不参与响应
Commit:执行事务提交
- commit请求 协调者向所有参与者发送commit请求
- 事务提交 参与者收到commit请求后,执行事务提交,提交完成后释放事务执行期占用的所有资源
- 反馈结果: 参与者执行事务提交后向协调者发送ACK响应
- 完成事务 接收到所有参与者的ACK响应后,完成事务提交
中断事务
在执行Prepare步骤过程中,如果某些参与者执行事务失败,宕机或与协调者之间的网络中断,那么协调者就无法收到所有参与者的YES响应,或者某个参与者返回了NO响应。此时,协调者就会进入回退流程,对事务进行会退。流程如下入红色部分(将commit请求替换成红色的RollBack请求)
分布式解决方案:AT模式
是一种物侵入的分布式事务的解决方案,阿里的seata框架实现了该模式。在AT模式下,用户只需要关注自己的业务SQL,用户的业务SQL作为一阶段,Seata框架会自动生成事务的二阶段提交和回滚操作
AT模式如何做到对业务的无侵入
- 一阶段:
在一阶段。Seata会拦截“业务SQL”,首先解析SQL语义,找到“业务SQL”需要更新的数据。在业务数据被更新钱,将其保存成”before image”,然后执行业务 SQL更新业务数据,在业务数据更新之后,在将其保存成“after image”。最后生成行锁。以上操作全部在一个数据库事务内完成,这样保证了操作的原子性
- 二阶段提交
二阶段如果提交的话,因为业务SQL在一阶段已经提交到数据库,所以Seata框架只需要将一阶段保存的快照数据和行锁删掉,完成数据清理即可
- 二阶段回滚
二阶段如果是回滚的话,Seata就需要回滚一阶段已经执行的业务SQL,还原业务数据,回滚方式便是用before image 还原业务数据;但在还原前要首先要校验脏写,对比数据库当前业务数据和after image,如果两份数据完全一致就说明没有脏写,可以还原业务数据,如果不一致就说明有脏写,出现脏写就需要人工处理。
分布式解决方案:TCC模式
需要用户根据自己的业务场景实现Try、Confirm和Cancel三个操作;事务发起方在一阶段执行Try方式,在二阶段提交执行Confirm方法,二阶段回滚操作执行Cancel方法
可靠消息最终一致性方案
Seata的AT模式原理
Seata服务搭建-db数据源
Seata Server(TC环境部署)
Server端存储模式(store.mode)支持三种
- file:单机模式,全局事务会话信息内存中读写并持久化本地文件root.data,性能较高(默认)
db:高可用模式,全局事务会话信息通过db共享,响应性能差些
修改安装目录下的
/conf/file.conf
文件,修改对应的模式为mode=db
,修改数据库的连接信息```transaction log store, only used in seata-server
store {
store mode: file、db、redis
修改这里的模式为数据库模式(db)
mode = “db”
file store property
file {
store location dir
dir = “sessionStore”
branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions
maxBranchSessionSize = 16384
globe session size , if exceeded throws exceptions
maxGlobalSessionSize = 512
file buffer size , if exceeded allocate new buffer
fileWriteBufferCacheSize = 16384
when recover batch read size
sessionReloadReadSize = 100
async, sync
flushDiskMode = async }
database store property
修改数据库的信息
db {
the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari) etc.
datasource = “druid”
mysql/oracle/postgresql/h2/oceanbase etc.
dbType = “mysql”
新旧版本的数据库所用的驱动是不同的
driverClassName = “com.mysql.cj.jdbc.Driver” url = “jdbc:mysql://62.234.130.20:3306/seata_server” user = “ecology” password = “192612” minConn = 5 maxConn = 30 globalTable = “global_table” branchTable = “branch_table” lockTable = “lock_table” queryLimit = 100 maxWait = 5000 }
redis store property
redis { host = “127.0.0.1” port = “6379” password = “” database = “0” minConn = 1 maxConn = 10 queryLimit = 100 }
} ```
- 通过查看资源找到对应版本下的
/script/server/db/..
对应版本的数据库脚本语句,在上述新建的数据库中执行- redis:Seata-server1.3及以上版本支持,性能较高,存在事务信息丢失风险,请提前配置适合当前场景的redis持久化配置
资源目录 - client:存放client端sql脚本,参数配置
- config-center:各个配置中心参数导入脚本,config.txt(包含server和client,原名为nacos-config.txt)为通用文件
- server:server端数据库脚本及各个容器配置
- redis:Seata-server1.3及以上版本支持,性能较高,存在事务信息丢失风险,请提前配置适合当前场景的redis持久化配置
db存储模式+Nacos(注册&配置中心)
Seata服务搭建-nacos
配置Nacos注册中心 负责事务参与者(微服务)和TC通信
将seata server 注册到Nacos、修改conf目录下的registry.conf配置文件
修改对应的配置中心
配置参数同步到Nacos
执行下载的scirpt中的nacos-config.sh的脚本
若是nacos开启了权限,注册的时候需要带有用户名和密码
出现一下文字说明注册成功
nacos-config.sh需要从源码工程上获取
Set transport.serialization=seata successfully
Set transport.compressor=none successfully
Set metrics.enabled=false successfully
Set metrics.registryType=compact successfully
Set metrics.exporterList=prometheus successfully
Set metrics.exporterPrometheusPort=9898 successfully
=========================================================================
Complete initialization parameters, total-count:79 , failure-count:0
=========================================================================
执行的命令:sh nacos-config.sh -p 8847
参数说明:
- -h:host,默认值是localhost
- -p:port,默认值是8848
- -g:配置分组,默认值为“SEATA_GROUP”
- -t:租户信息,对应nacos的命名空间ID字段,默认值为空
配置完各种各种信息就可以启动服务
./seata-server.sh
,端口是8091
分布式事务代码搭建
声明式服务的实现:@GlobalTransactional
接入微服务应用
业务场景:
用户下单,整个业务有三个微服务构成
- 订单服务:根据采购需求创建订单
- 库存服务:对给定的商品和扣除库存数量
启动seata server端,seata server使用nacos作为配置中心和注册中心
配置微服务整合seata
第一步:添加依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
</dependency>
第二步:各微服务对应的数据库中添加undo_log表
第三步: 修改register.conf,配置nacos作为register.type&config.type,对应的seata_server也使用nacos
注意:需要指定group=”SEATA_GROUP”,因为seata server端指定了group=”SEATA_GROUP”必须保持一致