事务提交 commit 会失败么_分布式事务设计与实践-TCC与Saga

0b4c90df502ad0999840240eb08851e8.png

分布式事务概述

分布式事务产生背景

7fe5fdeb6cce81443c76bc71badffed8.png
  1. 传统的单体应用,商品服务,用户服务和交易服务程序都编写在一个单体项目中,通过启动一个JVM进程和连接一个数据库就能提供所有功能,这时就可以通过数据库的ACID来保证事务一致性。
  2. 随着业务的发展和技术的发展,衍生出了上图的微服务架构,各个服务都是一个独立的JVM进程,并且都有自己独立的数据库和缓存服务,这时通过数据库本地事务无法保证分布式业务的一致性。

分布式事务分类

1.刚性事务

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

2.柔性事务

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

cb11b7926363860c326e3a82c7015155.png

刚性事务

满足传统事务特性

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

满足XA模型

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

6080d319e51935fc5144283bd2be3db7.png

2PC(两阶段提交)是XA规范标准实现

78a7bf34f2b98ec1ba1ff5f88a0bfe6e.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补偿方式:

向后恢复:补偿所有已完成的事务,本质就是所有已完成的本地事务进行回滚操作

向前恢复:重试失败的事务,假设每个子事务最终都会成功

6b342a0f5babcb9d3997490d9d3c7aaf.png

1.业务逻辑层调用加上事务注解@Around(“execution( (..)) && @annotation(TX)”),在业务入口方法加上这个事务注解,表明开启一个全局事务。

2.AOP在真正调用业务逻辑调用之前生成一个全局唯一事务TXID标示事务组,TXID保存在ThreadLocal变量中,方法开始前写入,完成后清除,并把TXID写入到数据库中,并把事务组的状态置为开始状态。

3.业务逻辑层调用数据访问层之前,通过RPCProxy代理记录当前调用请求参数。

4.如果业务正常,调用完成之后,当前方法的调用记录存档或者删除,把全局事务状态标示为成功。如果业务异常,抛出异常,全局事务标示为失败,定时任务进行异步反向补偿。

51e4c4a1d06e93be88c9e8ebd2e84be3.png

Saga实现时序图

交易创建订单事务组正常流程:锁库存 -> 减红包 -> 创建订单

f5e1749511c81d965065a05888567ce4.png

交易创建订单事务组异常流程:

92f02dc0870600516c34494eabb7ce52.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环形切面的后置处理中把全局事务的状态修改为成功。
  • 业务操作中任何一个失败了时抛出异常,捕捉到异常后全局事务标示为失败,返回请求放失败。异步线程通过记录的补偿方法进行事务组向前回滚。

参考资料:

https://www.infoq.cn/article/z4Z1AkW1B3lp1NDw3jyG​www.infoq.cn 分布式柔性事务之Saga详解-奈学教育​ask.naixuejiaoyu.com
3c33771d90f599c7358d047f048b829d.png
https://www.naixuejiaoyu.com/nam.html​www.naixuejiaoyu.com
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值