Seata的四种模式介绍

发布于:2023-01-22 ⋅ 阅读:(19) ⋅ 点赞:(0) ⋅ 评论:(0)

什么时候需要用到分布式事务:

就是指不是单个服务或者单个数据库架构下产生的事务,例如:

  • 跨数据源的分布式事务
  • 跨服务的分布式事务

Seata有四种模式: XA、AT(默认)、TCC、Seaga

XA:强一致性,基于数据库隔离,无代码侵入,在一阶段不提交事务

AT:默认模式,基于全局锁隔离,无代码侵入,一阶段提交事务,在提交事务前,会记录undolog日志,性能比XA模式好,二阶段TC通知回滚,则根据undolog回滚,通知提交,则删除undolog日志。

TCC:性能最好,不需要依赖关系型数据库,但代码入侵读高。Try:冻结可用数据,Confirm:确认提交数据,删除冻结数据  Canel:恢复数据,将冻结数据恢复

Seaga: 用于长事务,例如A项目调另外一个公司的项目接口。

解决分布式事务的理论基础

CAP定理:Consistency原子性、Availability(可用性)、Partition tolerance(分区容错性)

矛盾:在分布式事务中一定存在P,即分区容错性。如果要保证可用性,则分区的机器会出现数据不一致,即AP。如果要保证一致性,则分区的机器不能向外提供服务,即CP。

BASE理论:是解决CAP的一种思路

Basically Avaiable(基本可用): 分布式系统出现故障时,允许损失部分可用性,即保证核心可用。

Soft State(软状态):在一定时间内,允许出现中间状态,即短暂的数据不一致性。

Eventually Consistent(最终一致性):虽然无法保证强一致性,但在软状态结束后,最终达到数据一致性。

实战:

1、在服务调用方部署TC,注意,导入jar包后会自动寻找本地的seata服务

<!--seata-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
    <exclusions>
        <!--版本较低,1.3.0,因此排除--> 
        <exclusion>
            <artifactId>seata-spring-boot-starter</artifactId>
            <groupId>io.seata</groupId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-spring-boot-starter</artifactId>
    <!--seata starter 采用1.4.2版本-->
    <version>${seata.version}</version>
</dependency>

2、修改调用方配置文件,根据namespace -->group-->service-->cluster定位TC服务集群

seata:
  registry: # TC服务注册中心的配置,微服务根据这些信息去注册中心获取tc服务地址
    type: nacos # 注册中心类型 nacos
    nacos:
      server-addr: 127.0.0.1:8848 # nacos地址
      namespace: "" # namespace,默认为空
      group: DEFAULT_GROUP # 分组,默认是DEFAULT_GROUP
      application: seata-tc-server # seata服务名称
      username: nacos
      password: nacos
  tx-service-group: seata-demo # 事务组名称
  service:
    vgroup-mapping: # 事务组与cluster的映射关系
      seata-demo: SH

Seata的XA模型:

RM一阶段:

1)TM开启全局事务

2)TM调用分支RM、RM将分支注册到TC、RM执行SQL(但不提交!)、RM将执行状态报告给TC

TC二阶段:

1)TM提交全局事务

2)TC统计各分支状态,如果都成功,则通知RM提交。如果失败,则通知RM回滚。

 Seata AT模型:

一阶段:TM开启全局事务、TM调用分支、RM注册分支事务、RM记录undolog日志、RM提交事务、TCC记录各分支状态

二阶段:TM通知提交/回滚全局事务、TC检查各分支事务状态,成功,则删除undolog日志,失败,则根据undolog日志回滚。

 脏写问题:

如果一个A事务执行sql并提交,另一个B事务也执行提交,此时A事务进行回滚,则会回滚为A记录的undolog日志,而B事务的更新修改记录会被忽略,出现了脏写问题。

 解决:引入全局锁,在A事务提价事务释放DB锁之前,申请全局锁,而此时如果B事务进行操作修改,在执行更新数据库操作前会获取全局锁,获取失败,则无法更新,不断重试,但不能一直让其重试,否则A尝试获取B占用的DB锁则会造成死锁,一般让其重试30秒,然后失败则放弃其占有的DB锁,执行失败。A锁此时就能获取DB锁,执行回滚,然后再释放全局锁。

又引来新问题:如果是另一不归seata管理的事务的?全局锁失败!

XA也自动带来了解决的方案:

1)首先记录更新前的记录

2)记录更新后的记录。

完整正确的执行流程如下:

1)原数据假设为100,undolog记录100这个数值。

2)A事务获取DB锁将数据修改为90,此时undolog记录这条90。

3)A事务获取全局锁,并提交事务释放DB数据库锁

4)A事务回滚,在回滚为100前,会比较此时数据是否是90。假设,不归Seata管理的B事务,不需要获取全局锁,然后成功获取DB锁并修改了数据为80,则此时A事务将90(A修改后)与80(B修改)比较,则回滚失败。

Seata TCC模型:

 Try: 判断是否有可用数据,足够则冻结可用数据。

Confirm:  完成资源的操作业务;要求try成功,confirm一定要成功。

Cancel: 预留资源释放,可以理解为try方向操作。

阶段1:检查资源是否足够,足够则冻结资源,执行try方法

阶段2:执行成功,则执行Confirm方法删除冻结资源。执行失败,执行Canel逻辑,恢复冻结资源

 四种事务优缺点介绍:

XA:强一致性,无代码侵入、但一阶段事务不提交、会锁住资源,导致性能低。需要依赖数据库的事务特性。

AT:默认,弱一致性,无代码侵入,一阶段事务直接提交,失败则根据undolog日志回滚,隔离性引入全局锁,但并发几率低,所以性能会比XA好。

TCC:无需依赖关系型数据库,基于资源预留隔离。try、confirm、canel需要人工手写,而且需要考虑空悬挂、空回滚、幂等性判断,较为复杂、性能最好,但成本太高。

Seaga:适用于长事务类型,无太多应用场景。