SpringCloud源码探析(十一)-分布式数据库Seata

1.概述

在分布式系统下,一个业务跨越多个服务或数据源,每一个服务都是一个分支事务,要保证所有分支事务最终状态一致,这样的事务就是分布式事务。分布式事务的参与者、支持事务的服务器、资源服务器及事务管理器分别位于不同的分布式系统的节点之上,且属于不同的应用,分布式事务需要保证这些操作要么全部成功,要么全部失败,本质上来说,分布式事务就是为了保证不同数据库的数据一致性。分布式事务框架目前使用较为广泛的分别是LCN和Seata,LCN定位于一款事务协调性框架,框架其本身并不操作事务,而是基于对事务的协调从而达到事务一致性的效果;Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。本文将分析Seata的基本原理,以及在分布式服务中如何使用Seata。

2.分布式概念及Seata使用

2.1 事务特性(ACID)

1、原子性(A):在整个事务中的所有操作,要么全部完成,要么全部不做,没有中间状态。对于事务在执行中发生错误,所有的操作都会被回滚,整个事务就像从没被执行过一样;

2、一致性(C):事务的执行必须保证系统的一致性;

3、隔离性(I):事务与事务之间不会互相影响,一个事务的中间状态不会被其他事务感知;

4、持久性(D):事务一旦完成,那么事务对数据库所做的变更就完全保存在了数据库中,即使发生停电或宕机,也不会发生改变。

2.2 CAP概念

CAP定理(CAP theorem)是由Eric Brewer在2000年PODC会议上提出,又被称作布鲁尔定理(Brewer’s theorem),是分布式系统中的一个基本定理。它指出任何分布式系统(Distributed System)中,多具有一致性(consistency)、可用性(availability)、分区容错(partition-tolerance)这三个特性中的两个。具体解释如下:

Consistenty(一致性):用户访问分布式系统中的任意节点,得到的数据必须一致;
Availability(可用性):用户访问集群中的任意健康节点,必须能得到响应,而不是超时或拒绝;
Partition(分区):因为网络故障或其他原因导致分布式系统中的部分节点与其它节点失去连接,形成独立分区;
Tolerance(容错性):在集群出现分区时,整个系统也要持续对外提供服务。

BASE理论是对CAP的一种解决思路,包含三个思想:

  • Basically Available(基本可用):分布式系统在出现故障时,允许损失部分可用性,即保证核心可用;
  • Soft State(软状态):在一定时间内,允许出现中间状态,比如临时的不一致状态;
  • Eventually Consisten(最终一致性):虽然无法保证强一致性,但是在软状态结束后,最终达到数据一致。

分布式事务最大的问题是各个子事务的一致性问题,因此可以借鉴CAP定理和BASE理论:

  • AP模式:各子事务分别执行和提交,允许出现结果不一致,然后采用弥补措施恢复数据即可,实现最终一致;
  • CP模式:各个子事务执行后互相等待,同时提交,同时回滚,达成强一致。但事务等待过程中,处于弱可用状态。

解决分布式事务,各个子系统之间必须能感知到彼此的事务状态,才能保证状态一致,因此需要一个事务协调者来协调每一个事务的参与者(子系统事务),下图展示一个下单流程,用户在进行下单时,订单服务会分别调用账户服务查看下单用户是否存在,同时调用库存服务查看所购买商品库存是否充足,事务协调者则协调这三个服务,具体如下:
在这里插入图片描述

解决分布式事务的思想和模型:

全局事务:整个分布式事务;
分支事务:分布式事务者包含的每个子系统的事务;
最终一致思想:各分支事务分别执行并提交,如果有不一致的情况,再想办法恢复数据;
强一致思想:各分支事务指向完业务不要提交,等待彼此结果,最后统一提交或回滚。

2.3 Seata中基础概念

Seata事务管理中有三个重要的角色:

TC(Transaction Coordinator,事务协调者):维护全局和分支事务的状态,协调全局事务提交或回滚;
TM(Transaction Manager,事务管理者):定义全局事务的范围,开始全局事务、提交或回滚全局事务;
RM(Resource Manager,资源管理器):管理分支事务处理的资源,与TC交谈以注册分支事务和报告分支事务的状态,并驱动分支事务体交或回滚。

Seata提供了四种不同的分布式事务解决方案:

  • XA模式:强一致性分阶段事务模式,牺牲了一定的可用性,无业务侵入;
  • TCC模式:最终一致性分阶段事务模式,有业务侵入;
  • AT模式:最终一致的分阶段事务模式,无业务侵入,也是Seata的默认模式;
  • SAGA模式:长事务模式,有业务侵入。

2.3.1 seata的XA模式

seata的XA模式流程主要分为两个阶段,具体如下:
在这里插入图片描述

1.RM一阶段工作

(1)注册分支事务到TC
(2)执行分支事务到TC
(3)报告执行状态到TC

2.RM二阶段工作

TC检测各分支事务状态
(1)如果都成功,通知所有RM提交事务;
(2)如果都失败,通知所有RM回滚事务。

XA模式的优缺点:

优势:事务强一致性,满足ACID原则;常用数据库都支持,实现简单,并且无代码侵入;
缺点:性能相对较差(一阶段锁定,二阶段提交);依赖关系型数据库实现事务。

2.3.2 实现XA模式

seata的starter已经完成了XA模式的自动装配,实现步骤如下:
1.修改application.yml(application.properties),开启XA模式,注意:每个参与事务的微服务都要修改

#seata开启XA模式配置
seata.data-source-proxy-mode=XA

2.在发起全局事物的入口方法上添加@GlobalTransactional注解,在本案例中是订单服务OrderServiceImpl中的insert()方法;

@GlobalTransactional
    public Order insert(Order order) {
    
    
        try {
    
    
            order.setCreateDate(new Date());
            order.setModifyDate(new Date());
            log.info("add order:{}", JSON.toJSONString(order));
            this.orderDao.insert(order);
            //扣用户余额
            userFeign.deduct(order.getUserId(), order.getTotalPrice());
            //扣库存
            storageFeign.deduct(order.getName(), order.getProductNum());
        } catch (Exception e) {
    
    
            log.error("下单异常:{}", e);
            throw new RuntimeException(e);
        }
        return order;
    }

3.重启订单服务进行测试。
服务在nacos中的注册情况如下:
在这里插入图片描述

案例中在创建订单时由于库存数量不够而触发事务回滚,各服务回滚日志如下:
(1)订单服务回滚日志在这里插入图片描述
(2)用户服务回滚日志
在这里插入图片描述
(3)库存服务回滚日志
在这里插入图片描述

2.3.3 AT模式

AT模式同样是分阶段提交的事务模型,不过弥补了XA模型中资源锁定周期过长的缺陷。
1.RM一阶段工作

(1)注册分支事务到TC
(2)记录undo-log(数据快照)
(3)执行业务sql并提交
(4)报告执行状态到TC

2.RM二阶段工作

TC检测各分支事务状态
(1)如果都成功,删除undo-log数据;
(2)如果失败,根据undo-log回复数据到更新前。

具体如下图所示:
在这里插入图片描述

AT模式与XA模式最大的区别是什么?

1.XA模式一阶段不提交事务,锁定资源;AT模式一阶段直接提交,不锁定资源;
2.XA模式依赖数据库机制实现回滚;AT模式利用数据快照实现数据回滚;
3.XA强一致;AT模式最终一致。

2.3.4 AT模式验证

1.修改订单服务、库存服务、用户服务配置

#seata开启AT模式配置,默认为AT模式
seata.data-source-proxy-mode=AT

2.验证
测试数据库存数量为3,创建新订单数量为5,理论上会抛出异常并进行回滚。
订单服务在第二阶段发生回滚:
在这里插入图片描述

2.3.5 TCC模式验证

TCC(Try-Confirm-Cancel)模式是分布式事务中的二阶段提交协议,资源预留(Try)、确认操作(Confirm)、取消操作(Cancel),具体含义如下:

Try:对业务资源的检查并预留 ,若分支事务的Try操作出现异常,则直接全局事务回滚,其他分支事务的Cancel被触发;若所有分支事务的Try操作均成功,则直接提交全局事务,所有分支事务的Confirm被触发;
Confirm:对业务处理进行提交,即commit操作,若try成功,需要保证confirm一定要成功;
Cancel:对业务处理进行取消,即回滚操作;若Cancel操作自身出现异常,则Cancel操作会被多次重复调用;

TCC模式的优缺点:

1.优点

  • 一阶段完成直接提交事务,释放数据库资源,性能好
  • 相比AT模型,无需生成快照,无需使用全局锁,性能最强
  • 不依赖数据库事务,而是依赖补偿操作,可以用于非事务型数据库;
    2.缺点
  • 有代码侵入,需要人为编写try、confirm和cancel接口,比较麻烦;
  • 软状态,事务是最终一致;
  • 需要考虑Confirm和Cancel的失败情况,做好幂等处理。

TCC的空回滚和业务悬挂:

空回滚:某分支事务的try阶段阻塞时,可能导致全局事务超时而触发二阶段的cancel操作;其它分支可能未执行try操作时先执行了cancel操作,这时cancel不能做回滚,就是空回滚;
业务悬挂:对于已经空回滚的业务,如果以后继续执行try,就永远不可能confirm或cancel。

以user-service进行改造,利用TCC实现分布式事务,具体如下:
为了实现空回滚、防止业务悬挂,以及满足幂等性要求。必须在数据库记录冻结金额的同时,记录当前事务id和执行状态,需要设计一张表:

CREATE TABLE `account_freeze_tbl` (
  `xid` varchar(128) NOT NULL AUTO_INCREMENT,
  `user_id` varchar(255) DEFAULT NULL COMMENT '用户id',
  `freeze_money` int(11) unsigned NULL COMMENT '年龄',
  `state` int(1) DEFAULT NULL COMMENT '事务状态 0try1:confirm,2:cancel'
  PRIMARY KEY (`xid`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

具体各部分业务逻辑如下:

Try业务:(1)记录冻结金额和事务状态到account_freeze_tbl表 (2)扣减account表可用金额
Confirm业务: 根据xid删除account_freeze_tbl表的冻结记录
Cancel业务:(1)修改account_freeze_tbl表冻结金额为0,state状态为2 (2)修改account表,恢复可用金额
判断是否空回滚: cancel业务中,根据xid查询account_freeze_tbl,如果为null则说明try还没开始,需要空回滚;
如何避免业务悬挂: try业务中,根据xid查询account_freeze_tbl表,如果已经存在则证明cancel已经执行,拒绝执行try业务。

2.3.6 SAGA模式

1.原理

Saga模式是一种用于处理分布式事务的模式,它通过将长时间的、复杂的事务分解为多个小的、可逆的事务片段,以实现事务的一致性和可靠性。
在Saga模式中,每个事务片段称为一个补偿操作。每个补偿操作都与一个正向操作相对应,正向操作是事务的一部分,而补偿操作是用于撤销或修复正向操作的。Saga模式通过按照事务执行的顺序,依次执行正向操作和补偿操作,来确保事务在发生失败或异常时能够进行回滚或恢复。

2.执行过程

1.执行正向操作:按照事务的逻辑顺序,依次执行正向操作。每个正向操作都会记录事务的执行状态。
2.如果所有的正向操作都成功执行,则事务提交完成。
3.如果某个正向操作失败,将会触发相应的补偿操作。补偿操作会撤销或修复正向操作的影响。
4.执行补偿操作:按照逆序依次执行已经触发的补偿操作。补偿操作应该具备幂等性,以便可以多次执行而不会造成副作用。
5.如果所有的补偿操作都成功执行,则事务回滚完成。
6.如果补偿操作也失败,需要人工介入或其他手段来解决事务的一致性问题。

3.适用场景

1.业务流程长、业务流程多;
2.参与者包含其它公司或遗留系统服务,无法提供 TCC 模式要求的三个接口。

4.四种模式对比
在这里插入图片描述

3.小结

1.seata默认模式是AT模式,具有弱一致性的优点,并且满足大多数分布式事务场景;
2.TCC和SAGA模式和差别在于TCC需要预留指定接口,并且在指定接口中实现各业务成功和失败回滚逻辑,SAGA模式是完全实现状态机和补偿业务;
3.在日常使用中,建议以AT模式和TCC模式作为主要模式,如果涉及业务流程较长,可能就需要梳理每一个业务阶段,实现状态机和补偿机制度。

4.参考文献

1.https://www.bilibili.com/video/BV1LQ4y127n4
2.https://baijiahao.baidu.com/s?id=1777717003459842931
3.https://zhuanlan.zhihu.com/p/246096231

5.附录

1.https://gitee.com/Marinc/nacos

猜你喜欢

转载自blog.csdn.net/qq_33479841/article/details/132777795
今日推荐