文章目录
一.分布式事务产生的背景
1.分布式架构演进之–数据库的水平拆分
蚂蚁金服的业务数据库起初是单库单表,但随着业务数据规模的快速发展,数据量越来越大,单库单表逐渐成为瓶颈。所以我们对数据库进行了水平拆分,将原单库单表拆分成数据库分片。
如下图所示,分库分表之后,原来在一个数据库上就能完成的写操作,可能就会跨多个数据库,这就产生了跨数据库事务问题。
2.分布式架构演进之–业务服务化拆分
在业务发展初期,“一块大饼”的单业务系统架构,能满足基本的业务需求。但是随着业务的快速发展,系统的访问量和业务复杂程度都在快速增长,单系统架构逐渐成为业务发展瓶颈,解决业务系统的高耦合、可伸缩问题的需求越来越强烈。
如下图所示,蚂蚁金服按照面向服务架构(SOA)的设计原则,将单业务系统拆分成多个业务系统,降低了各系统之间的耦合度,使不同的业务系统专注于自身业务,更有利于业务的发展和系统容量的伸缩。
因此,业务系统按照服务拆分之后,一个完整的业务往往需要调用多个服务,如何保证多个服务间的数据一致性成为一个难题。
二.分布式事务理论基础
1. 两阶段提交协议
两阶段提交协议:事务管理器分两个阶段来协调资源管理器,第一阶段准备资源,也就是预留事务所需的资源,如果每个资源管理器都资源预留成功,则进行第二阶段资源提交,否则协调资源管理器回滚资源。
2.TCC
TCC(Try-Confirm-Cancel) 实际上是服务化的两阶段提交协议,业务开发者需要实现这三个服务接口,第一阶段服务由业务代码编排来调用 Try 接口进行资源预留,所有参与者的 Try 接口都成功了,事务管理器会提交事务,并调用每个参与者的 Confirm 接口真正提交业务操作,否则调用每个参与者的 Cancel 接口回滚事务。
3.Saga
Saga 是一种补偿协议,在 Saga 模式下,分布式事务内有多个参与者,每一个参与者都是一个冲正补偿服务,需要用户根据业务场景实现其正向操作和逆向回滚操作。
分布式事务执行过程中,依次执行各参与者的正向操作,如果所有正向操作均执行成功,那么分布式事务提交。如果任何一个正向操作执行失败,那么分布式事务会退回去执行前面各参与者的逆向回滚操作,回滚已提交的参与者,使分布式事务回到初始状态。
Saga 理论出自 Hector & Kenneth 1987发表的论文 Sagas。
Saga 正向服务与补偿服务也需要业务开发者实现。
三.Seata理论基础
1.Seata是什么
Seata是一款开源的分布式事务解决方案,致力于在微服务架构下提供高性能和简单易用的分布式事务服务
1:1(单机模式) -> 1:N (单机多数据库)-> N: N(分布式,一个系统对应一个数据库)
一次业务操作需要跨多个数据源或需要跨多个系统进行远程调用,就会产生分布式事务问题
2.Seta能干嘛?
分布式事务处理过程的----ID+三组件模型
Transaction ID XID 全局唯一的事务ID
三组件概念:
Transaction Coordinator(TC) 事务协调器,维护全局事务的运行状态,负责协调并驱动全局事务的提交或回滚;
Transaction Manager(TM ) 控制全局事务的边界,负责开启一个全局事务,并最终发起全局提交或全局回滚的决议;
Resource Manager(RM) 控制分支事务,负责分支注册,状态汇报,并接收事务协调器的指令,驱动分支(本地)事务的提交和回滚;
处理过程:
3.SEATA的分布式交易解决方案
四.Senta安装与配置
-
下载地址:http://seata.io/zh-cn/blog/download.html
-
seata-server-0.9.0.zip解压到指定目录并修改conf目录下的file.conf配置文件
-
主要修改:自定义事务组名称+事务日志存储模式为db+数据库连接信息
-
建数据库seata
执行senta/conf/db_store.sql 语句
-
修改seata-server-0.9.0\seata\conf目录下的registry.conf配置文件
-
启动nacos,在启动seata
seata启动成功:softs\seata-server-0.9.0\seata\bin\seata-server.bat
五.Seata准备环境搭建
1.业务说明
下订单–>扣库存–>减账户(余额)—>修改订单状态
2.创建数据库
seata_order: 存储订单的数据库
seata_storage:存储库存的数据库
seata_account: 存储账户信息的数据库
创建表,sql语句去脑图自行复制
Seata出现事务异常时,会回滚并且记录到数据库里,按照上述3库分别建对应的回滚日志表,订单-库存-账户3个库下都需要建各自的回滚日志表
\seata-server-0.9.0\seata\conf目录下的db_undo_log.sql
最终效果
3.测试
没使用分布式事务前
在最后扣减余额的业务中模拟超时异常
结果:订单状态为0,库存已经减少,但是金额没变
使用分布式事务
解决:在业务controller开始添加
@GlobalTransactional(name = “fsp_tx_group”,rollbackFor = Exception.class)
name:自定义,要唯一
rollbackFor : 出现什么异常时回滚
其他参数:noRollbackForClassName :出现什么异常时不回滚,
结果:扣减金额出现异常后,3个数据库全都回滚
六.Seata原理简介
Simple Extensible Autonomous Transaction Architecture,简单可扩展自治事务框架
1.Seata分布式交易解决方案
seata将分布式事务看做一个全局事务,全局事务包含很多分支事务,每个微服务的事务看做分支事务,也就是每个微服务的本地事务
2.TC/TM/RM三大组件
3.分布式事务的4种模式
参考博客:https://blog.youkuaiyun.com/ljheee/article/details/99696571
Seata默认是AT模式,AT 模式是一种无侵入的分布式事务解决方案。
在 AT 模式下,用户只需关注自己的“业务 SQL”,用户的 “业务 SQL” 作为一阶段,Seata 框架会自动生成事务的二阶段提交和回滚操作。
AT 模式如何做到对业务的无侵入 :
-
一阶段:
1、Seata 会拦截“业务 SQL”,首先解析 SQL 语义,找到“业务 SQL”要更新的业务数据,在业务数据被更新前,将其保存成“before image”,2、然后执行“业务 SQL”更新业务数据,在业务数据更新之后,再将其保存成“after image”,
3、最后生成行锁。以上操作全部在一个数据库事务内完成,这样保证了一阶段操作的原子性。
-
二阶段提交:
二阶段如果是提交的话,因为“业务 SQL”在一阶段已经提交至数据库, 所以 Seata 框架只需将一阶段保存的快照数据和行锁删掉,完成数据清理即可。
-
二阶段回滚:
二阶段如果是回滚的话,Seata 就需要回滚一阶段已经执行的“业务 SQL”,还原业务数据。回滚方式便是用“before image”还原业务数据;但在还原前要首先要校验脏写,对比“数据库当前业务数据”和 “after image”,如果两份数据完全一致就说明没有脏写,可以还原业务数据,如果不一致就说明有脏写,出现脏写就需要转人工处理。
AT 模式的一阶段、二阶段提交和回滚均由 Seata 框架自动生成,用户只需编写“业务 SQL”,便能轻松接入分布式事务,AT 模式是一种对业务无任何侵入的分布式事务解决方案。