事务比较

AT 模式是⽆侵⼊的分布式事务解决⽅案,适⽤于不希望对业务进⾏改造的场景,⼏乎0学习成本。
TCC 模式是⾼性能分布式事务解决⽅案,适⽤于核⼼系统等对性能有很⾼要求的场景。
Saga 模式是长事务解决⽅案,适⽤于业务流程长且需要保证事务最终⼀致性的业务系统,Saga 模式⼀阶段就会提交本地事务,⽆锁,长流程情况下可以保证性能,多⽤于渠道层、集成层业务系统。事务参与者可能是其它公司的服务或者是遗留系统的服务,⽆法进⾏改造和提供 TCC要求的接⼝,也可以使⽤ Saga 模式。
XA 模式是分布式强⼀致性的解决⽅案,但性能低⽽使⽤较少。

分布式事务分类

image.png

1.刚性事务

  • 强一致性:各个业务操作必须在事务结束时全部成功,或者全部失败
  • XA模型
  • 满足CAP理论的CP

    2.柔性事务

  • 保证最终一致性,事务结束后在可接受的时间范围内,可能出现短暂的不一致,最终会达成一致性

  • 满足CAP理论的AP,满足BASE理论

    刚性事务

    满足传统事务特性

  • ACID(原子性,一致性,隔离性,持久性)

满足XA模型

  • 应用程序(AP):定义事务边界(事务开始与结束),并且访问事务边界内的资源
  • 资源管理器(RM):管理计算机共享的资源,资源即数据库
  • 事务管理器(TM):负责管理全局事务,分配全局事务ID,监测事务的执行速度,并负责事务的提交,回滚,失败恢复等。

2PC(两阶段提交)是XA规范标准实现image.png
实现过程:

  1. AP发起一个全局事务,并且创建一个全局事务ID
  2. TM发起prepare投票,RM对投票进行表决
  3. RM都同意后,TM发起commit提交。其中任何一个prepare时不同意,TM都会发起rollback。
  4. 在commit过程中,发生宕机等异常,在服务重启后根据XA recover再次进行补偿,保证最终commit操作成功。

缺点:

  1. 同步阻塞模型
  2. 数据库资源锁定时间过程
  3. 全局锁(隔离级别串行化),并发能力低
  4. 不适合长事务
  5. 在一些异常情况下会有问题,在commit之后,回复给TM的ack丢失了,这时会导致TM不知道commit到底是否成功了,从而衍生出了三阶段提交来解决这个问题。

    柔性事务

    满足CAP模型的CP,柔性事务是对XA协议的妥协,它通过降低强一致性,从而减少数据库资源的锁定时间,提升系统可用性。
    典型架构实现
  • TCC模型
  • Saga模型

    TCC模型

    TCC模型完全交由业务端实现,每个子业务都需要实现try-confirm-cancel接口,对业务侵入性很大。
    资源锁定需要业务自主实现。
    Try: 尝试执行事务,完成业务检查,预留必要的资源。
    confirm: 真正执行业务,不做业务资源检查
    cancel: 释放try阶段预留的业务资源
    我们通过一个转账案例来分析
    用户A向用户B转账500元
    汇款服务
    Try:
    1.检查A账户有效性,查看A账户是否存在或者未冻结。
    2.检查账户余额是否大于等于500元
    3.从A账户扣减500元,并且状态置为“转账中”
    4.记录一个转账日志或者消息
    Confirm:
    1.将“转账中”的状态改为“正常”状态
    2.生成转账流水,删除转账日志
    Cancel:
    1.账户余额加回500元
    2.账户状态改为“正常”
    收款服务
    Try:
    1.检查B账户是否正常
    Confirm:
    1.从转账日志或者消息中获取账户A往账户B转账500元
    2.账户B增加500元
    Cancel:
    不做操作

    Saga模型

    Saga模型把一个分布式事务拆分成多个本地事务,每个本地事务都有对应的执行模块和补偿模块(对应TCC的confirm和cancel),当任何一个事务失败时,可以通过调用补偿模块来进行恢复,达到事务最终一致性。
    Saga事务隔离性,业务层自己处理,通过冻结资源或者应用层加锁

    Saga补偿方式:

    向后恢复:补偿所有已完成的事务,本质就是所有已完成的本地事务进行回滚操作
    向前恢复:重试失败的事务,假设每个子事务最终都会成功
    image.png
    1.业务逻辑层调用加上事务注解@Around(“execution( (..)) && @annotation(TX)”),在业务入口方法加上这个事务注解,表明开启一个全局事务。
    2.AOP在真正调用业务逻辑调用之前生成一个全局唯一事务TXID标示事务组,TXID保存在ThreadLocal变量中,方法开始前写入,完成后清除,并把TXID写入到数据库中,并把事务组的状态置为开始状态。
    3.业务逻辑层调用数据访问层之前,通过RPCProxy代理记录当前调用请求参数。
    4.如果业务正常,调用完成之后,当前方法的调用记录存档或者删除,把全局事务状态标示为成功。如果业务异常,抛出异常,全局事务标示为失败,定时任务进行异步反向补偿。
    image.png
    总结:
    1.分布式事务产生的背景是:一个业务功能涉及操作多个具有独立数据库和缓存的服务。
    2.分布式事务分类:

  • 刚性事务:所有业务操作在事务结束是要么全部成功,要么全部失败,强一致性,并发低。

  • 柔性事务:可接受时间范围内,允许出现短暂的不一致性,最终达成一致性。

3.2PC两阶段提交:AP发起一个全局事务,TM发起一个prepare请求,RM在prepare阶段都执行成功,TM发起commit请求。在prepare阶段人意RM执行失败,TM发起rollback操作。
4.TCC主要涵盖try-confirm-cancel操作,这些操作都需要业务实现,堆业务侵入性比较大,而且比saga多一个提交阶段。
5.Saga是目前行业内落地较多的成功方案,由业务提供一个业务执行接口和一个补偿接口(需要满足幂等性)

  • 事务开启入口方法,开始一个aop环形切面,在方法调用前分配一个全局唯一事务ID,记录到数据库中并且初始化状态为开始。
  • 调用每个业务操作时,记录业务请求的参数,事务提交方法和回滚方法信息。
  • 所有业务操作正常执行完后,在aop环形切面的后置处理中把全局事务的状态修改为成功。
  • 业务操作中任何一个失败了时抛出异常,捕捉到异常后全局事务标示为失败,返回请求放失败。异步线程通过记录的补偿方法进行事务组向前回滚。