分布式事务 Seata

目录

  • 分布式事务
      • 产生原因
      • CAP定理
      • BASE理论
      • 分布式事务解决思路
      • 2pc&3pc
  • Seata
      • Seata架构
      • 四种方案
  • 部署TC服务器
  • 微服务集成Seata
  • XA模式
      • XA规范
      • Seata的XA模式
  • AT模式
  • TCC模式
  • Saga模式
  • MQ解决分布式事务

分布式事务

分布式事务 Seata_第1张图片

产生原因

在一个整套业务中,一个业务的失败回滚对其他业务不可见(子事务不一致

CAP定理

  • 一致性:用户访问分布式系统中的任意节点,得到的数据必须一致;(及时同步)
  • 可用性:用户访问集群中的任意健康节点,必须得到响应,而不是超时或拒绝
  • 分区容错性:多个节点形成独立的分区,一个节点挂掉,整个系统也必须能够对外提供服务

在分布式中,分区容错必须实现,所有只能满足一致性和可用性的一种

BASE理论

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

  • 基本可用:分布式系统出现故障时,允许损失部分可用,保证核心可用
  • 软状态:允许出现中间状态,比如临时不一致、临时可用
  • 最终一致性: 最终达到数据一致

分布式事务解决思路

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

分布式事务 Seata_第2张图片

2pc&3pc

2pc

二阶段提交 分准备提交两个阶段;是一种强一致性设计;

  1. 准备阶段协调者会给各参与者发送准备命令,参与者会执行完sql但不提交;
  2. 第二阶段检查各事务状态,决定提交或回滚并通知各参与者;

特点

  • 阻塞资源:占用数据库资源,性能低,可用性低
  • 单点故障:协调者出错,事务失败
  • 数据不一致:二阶段出错,通知提交或回滚时断网

3pc

准备预提交提交三个阶段

  1. 准备:协调者只询问参与者是否可以提交事务,如果所有参与者都反馈yes 才能进入下一个阶段;这一个阶段时不锁表
  2. 预提交:这个阶段各分支事务执行完自己的操作,但不提交
  3. 提交:提交或回滚

特点

  • 降低了参与者同步阻塞范围,但是又引入了数据不一致性问题(若出现网络分区)、单点问题依然存在;

Seata

致力于提供高性能和易于使用的分布式事务服务,提供一站式分布式解决方案

Seata架构

  • 事务管理器 TM:定义全局事务的范围;开始全局事务;提交或回滚全局事务
  • 事务协调者 TC:维持全局和分支事务的状态;协调全局事务的提交、回滚
  • 资源管理器 RM:管理分支事务处理的资源;与事务协调器交谈以及注册分支事务和报告分支事务的状态,并驱动分支事务的提交或回滚
    分布式事务 Seata_第3张图片

四种方案

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

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

部署TC服务器

  1. https://seata.io/zh-cn/blog/download.html下载seata-server-1.4.2.zip
  2. 更改registry.conf配置:将配置和注册中心都改为nacos
    registry {
      # 注册中心类型 file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
      type = "nacos"
    
      nacos {
        application = "seata-tc-server"
        serverAddr = "127.0.0.1:8848"
        group = "DEFAULT_GROUP"
        namespace = ""
        cluster = "default"
        username = "nacos"
        password = "nacos"
      }
    }
    
    config {
      # file、nacos 、apollo、zk、consul、etcd3
      type = "nacos"
    
      nacos {
        serverAddr = "127.0.0.1:8848"
        namespace = ""
        group = "SEATA_GROUP"
        username = "nacos"
        password = "nacos"
        dataId = "seataServer.properties"
      }
    }
    
  3. 在nacos添加配置seataServer.properties
  4. 在seata数据库创建表seata-tc-server.sql
  5. cd Program Files\seata\seata-server-1.4.2\bin启动TC服务seata-server.bat
    分布式事务 Seata_第4张图片

微服务集成Seata

  1. 引入依赖
    
         <dependency>
             <groupId>com.alibaba.cloudgroupId>
             <artifactId>spring-cloud-starter-alibaba-seataartifactId>
             <exclusions>
                 <exclusion>
                     <artifactId>seata-spring-boot-starterartifactId>
                     <groupId>io.seatagroupId>
                 exclusion>
             exclusions>
         dependency>
         <dependency>
             <groupId>io.seatagroupId>
             <artifactId>seata-spring-boot-starterartifactId>
             <version>1.4.2version>
         dependency>
    
  2. 更改配置
    seata:
      registry:
        type: nacos
        nacos:
          server-addr: 127.0.0.1:8848
          namespace: ""
          group: DEFAULT_GROUP
          application: seata-tc-server
          username: nacos
          password: nacos
      tx-service-group: seata-demo # 事务组名称
    #  service:
    #    vgroup-mapping: # 事务组与cluster的映射关系
    #      seata-demo: SH
      data-source-proxy-mode: AT
      config:
        type: nacos
        nacos:
          server-addr: 127.0.0.1:8848
          username: nacos
          password: nacos
          group: SEATA_GROUP
          data-id: client.properties
    

XA模式

资源管理器RM(数据库事务)把自己的事务告诉事务协调者TC,随后都报告事务的状态,TC在得知每个事务的状态后决定统一提交或者回滚
分布式事务 Seata_第5张图片

XA规范

定义事务协调者和数据库之间的接口规范;事务协调者通过它来通知数据库事务的开始、结束、提交、回滚

XA接口函数由数据库厂商提供

Seata的XA模式

分布式事务 Seata_第6张图片

特点

  • 强一致性
  • 占用数据库锁,可用性降低
  • 需要数据库支持事务

实现
分布式事务 Seata_第7张图片

AT模式

解决XA资源锁定时间过长的缺陷
分布式事务 Seata_第8张图片

  1. RM向TC注册分支事务
  2. 执行SQL并提交,记录更改后的快照(undo log)
  3. 向TC报告事务的状态
  4. TC检查各个分支事务状态
  5. TC告诉RM提交或回滚。提交:删除log;回滚:恢复log数据并删除

XA与AT区别

  • XA一阶段不提交事务,锁定资源;AT提交事务,不锁资源
  • XA依赖数据库回滚;AT依赖日志记录快照实现数据回滚
  • XA强一致;AT最终一致

AT模式脏写问题

多线程中,一个事务A保存快照之后改变数据且提交,该事务数据库锁释放,另一事务B在此对这条数据进行修改且提交,TC告诉A事务应该回滚,B就发生脏写
分布式事务 Seata_第9张图片
对此引入全局锁,由TC去记录正在操作的数据库某行数据。

  1. 在A事务执行完SQL获取全局锁,TC就记录了这行数据,然后A事务提交,释放数据库锁;
  2. B事务就可以获取数据库锁,执行完SQL要提交的时候获取不到全局锁,就一直重试去拿全局锁;
  3. 如果A事务回滚就要重新拿数据库锁,但是数据库锁真正被B事务持有,形成死锁;所以事务B在默认重试30次后回滚释放数据库锁;

分布式事务 Seata_第10张图片
又出现了问题就是,如果有一个Seata没有管理的事务,这个事务就不用获取全局锁,还是会出现问题;

于是A事务就在执行SQL前后分别保存快照,回滚时对比提交后事务是否被改过;
分布式事务 Seata_第11张图片
特点

  • 锁粒度小,性能好
  • 全局锁,读写隔离
  • 没有侵入代码
  • 软状态,最终一致

实现
分布式事务 Seata_第12张图片

TCC模式

原理

与AT一样第一阶段提交事务,但TCC是靠人工编码实现数据恢复

  • Try:资源的检测和预留
  • Confirm:完成业务操作;要求Try成功Confirm一定成功
  • Cancel:预留资源的释放(Try的反向操作)

分布式事务 Seata_第13张图片

  1. 第一阶段与AT一样,分支事务执行(Try)提交之后报告事务状态
  2. 第二阶段TC检查完各分支事务状态后告诉各分支是提交还是回滚;提交:分支事务执行Confirm;回滚执行Cancel
    分布式事务 Seata_第14张图片

特点

  • 没有快照和全局锁,性能最好
  • 不依赖数据库事务,而是依赖补偿操作
  • 要多写代码
  • 软状态,最终一致
  • 要考虑到Confirm和Cancel失败的情况,做好幂等处理

分布式事务 Seata_第15张图片

空回滚和业务悬挂

  1. 当某个分支事务的Try阶段业务阻塞,可能导致全局事务超时而集体回滚;
  2. 但是这个事务没有执行Try,就多了一次Cancel操作,这就是空回滚;
  3. 于是就要在执行Cancel时判断这个事务是否执行了Try;
  4. 而对于已经空回滚的事务,之后又突然执行了Try,但是整体事务已经结束,这个事务就多执行了一次Try,这就是业务悬挂;
  5. 于是就要在执行Try是判断是否已经回滚过了

需要在数据库里记录当前事务的状态
分布式事务 Seata_第16张图片
实现
分布式事务 Seata_第17张图片

Saga模式

分布式事务 Seata_第18张图片

分布式事务 Seata_第19张图片

MQ解决分布式事务

转账:如果减余额和加余额两个操作需要同时执行,那么就等减余额成功后发送消息给加余额服务,这样保证MQ的可靠性就能保证事务(发布确认+持久化+手动应答)

如果下游服务要回滚(业务问题),那只能把这个问题的判断交给上游(项目超卖)

????


消费者在执行完事务后才根据提交还是回滚来决定是否应答该消息;所以mq要设置手动应答
分布式事务 Seata_第20张图片

  1. 上游服务向MQ发送一个半消息
  2. 然后执行本地事务
  3. 根据本地事务的执行结果向MQ发送commit或callback
  4. 如果是callback MQ就丢弃该消息,如果是commit就发送给下游

下游事务执行要等待上游服务执行完成并提交

你可能感兴趣的:(advance,分布式,微服务,事务,seata)