传统事务原则:ACID

image.png

分布式事务

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

  1. - 跨数据源的分布式事务
  2. - 跨服务的分布式事务
  3. - 综合情况

CAP定理

image.png
CAP理论中这三个指标不可能同时做到。这个结论就叫做 CAP 定理。
C:Consistency(一致性):用户访问分布式系统中的任意节点,得到的数据必须一致。
Availability (可用性):用户访问集群中的任意健康节点,必须能得到响应,而不是超时或拒绝。
Partition(分区):因为网络故障或其它原因导致分布式系统中的部分节点与其它节点失去连接,形成独立分区。

矛盾

  1. 在分布式系统中,系统间的网络不能100%保证健康,一定会有故障的时候,而服务有必须对外保证服务。
  2. 因此Partition Tolerance不可避免。
  3. 如果此时要保证一致性,就必须等待网络恢复,完成数据同步后,整个集群才对外提供服务,服务处于
  4. 阻塞状态,不可用。
  5. 如果此时要保证可用性,就不能等待网络恢复,就会出现数据不一致。

BASE理论

  1. BASE理论是对CAP的一种解决思路,包含三个思想:
  2. - Basically Available (基本可用):分布式系统在出现故障时,允许损失部分可用性,即保证核心可用。
  3. - Soft State(软状态):在一定时间内,允许出现中间状态,比如临时的不一致状态。
  4. - Eventually Consistent(最终一致性):虽然无法保证强一致性,但是在软状态结束后,最终达到数据一
  5. 致。

解决分布式事务

  1. 事务协调者(TC):都需要在子系统事务之间互相通讯,协调事务状态
  2. 这里的子系统事务,称为分支事务;有关联的各个分支事务在一起称为全局事务。

image.png

Seata

微服务集成Seata

  1. 1..引入依赖
  2. 2.配置TC地址

XA模式

  1. XA 规范 X/Open 组织定义的分布式事务处理(DTPDistributed Transaction Processing)标准,
  2. XA 规范 描述了全局的TM与局部的RM之间的接口,几乎所有主流的数据库都对 XA 规范 提供了支持。

XA是规范,目前主流数据库都实现了这种规范,实现的原理都是基于两阶段提交。
image.png

  1. 一阶段:
  2. - 事务协调者通知每个事物参与者执行本地事务
  3. - 本地事务执行完成后报告事务执行状态给事务协调者,此时事务不提交,继续持有数据库锁
  4. 二阶段:
  5. - 事务协调者基于一阶段的报告来判断下一步操作
  6. - 如果一阶段都成功,则通知所有事务参与者,提交事务
  7. - 如果一阶段任意一个参与者失败,则通知所有事务参与者回滚事务

XA模型

image.png

  1. RM一阶段的工作:
  2. 注册分支事务到TC
  3. 执行分支业务sql但不提交
  4. 报告执行状态到TC
  5. TC二阶段的工作:
  6. - TC检测各分支事务执行状态
  7. a.如果都成功,通知所有RM提交事务
  8. b.如果有失败,通知所有RM回滚事务
  9. RM二阶段的工作:
  10. - 接收TC指令,提交或回滚事务

XA优缺点

优点:

  • 事务的强一致性,满足ACID原则。
  • 常用数据库都支持,实现简单,并且没有代码侵入

缺点:

  • 因为一阶段需要锁定数据库资源,等待二阶段结束才释放,性能较差
  • 依赖关系型数据库实现事务

    XA的实现

    1. 1)修改application.yml文件(每个参与事务的微服务),开启XA模式:
    2. seata:
    3. data-source-proxy-mode: XA
    4. 2)给发起全局事务的入口方法添加@GlobalTransactional注解:
    5. 3)重启服务并测试

    AT模式

    基本流程

    image.png
    阶段工作 ```java 阶段一RM的工作:

  • 注册分支事务

  • 记录undo-log(数据快照)
  • 执行业务sql并提交
  • 报告事务状态

阶段二提交时RM的工作:

  • 删除undo-log即可

阶段二回滚时RM的工作:

  • 根据undo-log恢复数据到更新前
  1. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/26552815/1656593991624-773be3fe-6756-48e9-897e-ce3b12fd62d8.png#clientId=uacc64878-a3a4-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=329&id=uf7358af5&margin=%5Bobject%20Object%5D&name=image.png&originHeight=658&originWidth=742&originalType=binary&ratio=1&rotation=0&showTitle=false&size=57832&status=done&style=none&taskId=u3738e7e1-9ee4-4625-a11e-d478632589b&title=&width=371)
  2. <a name="Fo7bU"></a>
  3. ## AT与XA的区别
  4. ```java
  5. - XA模式一阶段不提交事务,锁定资源;AT模式一阶段直接提交,不锁定资源。
  6. - XA模式依赖数据库机制实现回滚;AT模式利用数据快照实现数据回滚。
  7. - XA模式强一致;AT模式最终一致

AT模式脏写问题

解决思路:引入了全局锁的概念。在释放DB锁之前,先拿到全局锁。避免同一时刻有另外一个事务来操作当前数据。

优缺点

AT模式的优点:

- 一阶段完成直接提交事务,释放数据库资源,性能比较好
- 利用全局锁实现读写隔离
- 没有代码侵入,框架自动完成回滚和提交

AT模式的缺点:

- 两阶段之间属于软状态,属于最终一致
- 框架的快照功能会影响性能,但比XA模式要好很多

AT模式实现

1)导入数据库表,记录全局锁
2)修改application.yml文件,将事务模式修改为AT模式即可:
seata:
  data-source-proxy-mode: AT # 默认就是AT
3)重启服务并测试