1 事务回顾

事务的ACID是通过日志和锁来实现的。

数据库锁

隔离性是通过 MVCC来实现的。

undo log 和 redo log

事务中,每执行一条sql语句对数据造成影响时,就会记录这条语句到redo log中,同时也会记录一条与之相反的操作到undo log。 如:开启事务insert一条记录时,redo log和undo log同时分别记录了这条sql和相反操作的sql。当事务提交时,redo log中的操作将被持久化;当事务回滚时,执行Undo log中的操作,delete掉生成的数据。

原子性和一致性是通过 Undo log(回滚日志)来实现的
持久性是通过 redo log (重做日志) 来实现的

mysql在生成redo log时,会使用innodb log buffer ,先缓冲到内存,再同步到redo log,速度更快。

2 分布式事务概述

定义: 分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同分布式系统的不同节点上。

  • 服务存在多个节点 (应用层)
  • 资源存在多个节点 (db层)

CAP

  1. 分布式基础-通俗易懂CAP
中文名 英文 说明
C:强一致性 Consistency 一个分布式节点修改了数据,另一个节点能即时读到最新数据。
A:高可用性 Availability 非故障节点在合理时间返回合理响应。
P:分区容错性 Partition Tolerance 网络分区故障系统仍能运行。如某台服务器挂掉

分布式事务 - 图1

  • cap三者不可全得,只能保证任意两两组合。
  • P一般必选,所以常用CP和AP

BASE

Basically Available 基本可用 保证核心功能可用,允许丢失功能
Soft state 软状态 允许存在中间状态,这个状态不影响系统可用
Eventually Consitent 最终一致性 经过一定时间后,所有数据最终达到一致

3. 解决方案

  • 无业务侵入 如XA
  • 有业务侵入 如TCC

    2pc二阶段提交

  • 成功,全局提交

image.png

  • 失败,全局回滚

image.png

故障分析

一阶段故障
  • 协调者:
    • 在发起全局事务前挂了,无影响
    • 发起全局事务后挂了,考虑某些参与者已经业务处理完毕,阻塞等待提交的状态,事务无法继续且占用资源,
      • 1等待时间
      • 2定期轮询协调者状态,无法获取通知一定次数回滚
    • 发起全局回滚/全局提交之前挂了,问题有点严重,所有人都把事情做好了,却都白做了且还会阻塞一段时间占用资源
      • 选举新的协调者主事,每个参与者提供状态回查服务,新的协调者轮询各参考者状态,组织全局回滚或全局提交
    • 发起全局回滚/全局提交之后挂了,影响不大,所有人安全落地
      二阶段故障
  1. 二阶段执行回滚操作失败:不断重试,直到所有参与者都回滚,此时协调者与其他已回滚成功者都处于阻塞状态。
  2. 二阶段执行commit操作失败: 不断重试,只能铁着头前进,直到提交成功,重试多次无法成功,只好人工介入。
    特点
  • 尽量保证强一致性
  • 同步阻塞
  • 效率低
  • 极端情况下存在数据不一致风险

    3PC 三阶段提交

    canCommit, preCommit, doCommit
    image.png

    TCC

    2pc和3pc都是数据库层面的,而tcc是业务层面的分布式事务

image.png

本地消息表

存放本地消息的表,一般放在数据库中,然后在执行业务的时候把业务的执行和将消息放入消息表的操作放在同一个事务中,这样就能保证消息放入本地中业务肯定是执行成功的。全局提交前,协调者去本地消息表查询所有未执行成功的消息,再次重试调用。
需要重试就需要参与者业务幂等,且重试要最大次数,超出后报警人工处理。
本地消息表容忍数据暂时不一致,实现最终一致性。

消息事务(RocketMQ)

半消息:已发送成功到broker但对消费者不可见的消息
先发送半消息,再根据本地事务的结果向broker发送commit或者rollback命令。
如果commit那么订阅就能收到这条消息,然后消费;如果rollback那么订阅方收不到这条消息,等于事务没有执行过。
image.png

最大努力通知

本地消息表和MQ事务消息也算是最大努力通知
适用于对时间不敏感的业务,例如短信通知。

4 Seata

AT模式

一阶段:业务数据和回滚日志记录 在同一本地事务中提交,释放本地锁和资源。
二阶段:

  • 回滚通过一阶段的回滚日志进行反向补偿
  • 此期间对一阶段提交数据上独占写锁

一阶段本地事务提交后,加全局锁,全局锁使用select for update来实现,使用独占写锁直到全局提交或回滚;
通过记录undolog来回滚

TCC

AT依赖关系型数据,tcc则不需要