《我想进大厂》之分布式事务篇(二)

wg204wg
发布于 2022-6-9 16:41
浏览
0收藏

 

SAGA

Saga源于1987 年普林斯顿大学的 Hecto 和 Kenneth 发表的如何处理 long lived transaction(长活事务)论文。

主要思想就是将长事务拆分成多个本地短事务。

如果全部执行成功,就正常完成了,反之,则会按照相反的顺序依次调用补偿。

SAGA模式有两种恢复策略:

向前恢复,这个模式偏向于一定要成功的场景,失败则会进行重试
向后恢复,也就是发生异常的子事务依次回滚补偿
由于这个模式在国内基本没看见有谁用的,不在赘述。

消息队列

基于消息队列来实现最终一致性的方案,这个相比前面的我个人认为还稍微靠谱一点,那些都是理论啊,正常生产的实现很少看见应用。

基于消息队列的可能真正在应用的还稍微多一点。

一般来说有两种方式,基于本地消息表和依赖MQ本身的事务消息。

本地消息表的这个方案其实更复杂,实际上我也没看到过真正谁来用。这里我以RocketMQ的事务消息来举例,这个方式相比本地消息表则更完全依赖MQ本身的特性做了解耦,释放了业务开发的复杂工作量。

 《我想进大厂》之分布式事务篇(二)-鸿蒙开发者社区

  1. 业务发起方,调用远程接口,向MQ发送一条半事务消息,MQ收到消息之后会返回给生产者一个ACK
  2. 生产者收到ACK之后,去执行事务,但是事务还没有提交。
  3. 生产者会根据事务的执行结果来决定发送commit提交或者rollback回滚到MQ
  4. 这一点是发生异常的情况,比如生产者宕机或者其他异常导致MQ长时间没有收到commit或者rollback的消息,这时候MQ会发起状态回查。
  5. MQ如果收到的是commit的话就会去投递消息,消费者正常消费消息即可。如果是rollback的话,则会在设置的固定时间期限内去删除消息。
    这个方案基于MQ来保证消息事务的最终一致性,还算是一个比较合理的解决方案,只要保证MQ的可靠性就可以正常实施应用,业务消费方根据本身的消息重试达到最终一致性。

框架

以上说的都是理论和自己实现的方式,那么分布式事务就没有框架来解决我们的问题吗?

有,其实还不少,但是没有能扛旗者出现,要说有,阿里的开源框架Seata还有阿里云的GTS。

GTS(Global Transaction Service 全局事务服务)是阿里云的中间件产品,只要你用阿里云,付钱就可以用GTS。

Seata(Simple Extensible Autonomous Transaction Architecture)则是开源的分布式事务框架,提供了对TCC、XA、Saga以及AT模式的支持。

那么,GTS和Seata有什么关系呢?

实际上最开始的时候他们都是基于阿里内部的TXC(Taobao Transaction Constructor)分布式中间件产品,然后TXC经过改造上了阿里云就叫做GTS。

之后阿里的中间件团队基于TXC和GTS做出了开源的Seata,其中AT(Automatic Transaction)模式就是GTS原创的方案。

至于现在的版本,可以大致认为他们就是一样的就行了,到2020年,GTS已经全面兼容了Seata的 GA 版本。

《我想进大厂》之分布式事务篇(二)-鸿蒙开发者社区

 图片来自阿里云官网GTS

整个GTS或者Seata包含以下几个核心组件:

  • Transaction Coordinator(TC):事务协调器,维护全局事务的运行状态,负责协调并驱动全局事务的提交或回滚。
  • Transaction Manager(TM):控制全局事务的边界,负责开启一个全局事务,并最终发起全局提交或全局回滚的决议。
  • Resource Manager(RM):控制分支事务,负责分支注册、状态汇报,并接收事务协调器的指令,驱动分支(本地)事务的提交和回滚。
    无论对于TCC还是原创的AT模式的支持,整个分布式事务的原理其实相对来说还是比较容易理解。
  1. 事务开启时,TM向TC注册全局事务,并且获得全局事务XID
  2. 这时候多个微服务的接口发生调用,XID就会传播到各个微服务中,每个微服务执行事务也会向TC注册分支事务。
  3. 之后TM就可以管理针对每个XID的事务全局提交和回滚,RM完成分支的提交或者回滚。

《我想进大厂》之分布式事务篇(二)-鸿蒙开发者社区
 核心组件定义-图片来自阿里云官网

AT模式

原创的AT模式相比起TCC的方案来说,无需自己实现多个接口,通过代理数据源的形式生成更新前后的UNDO_LOG,依靠UNDO_LOG来实现回滚的操作。

执行的流程如下:

  1. TM向TC注册全局事务,获得XID
  2. RM则会去代理JDBC数据源,生成镜像的SQL,形成UNDO_LOG,然后向TC注册分支事务,把数据更新和UNDO_LOG在本地事务中一起提交
  3. TC如果收到commit请求,则会异步去删除对应分支的UNDO_LOG,如果是rollback,就去查询对应分支的UNDO_LOG,通过UNDO_LOG来执行回滚

《我想进大厂》之分布式事务篇(二)-鸿蒙开发者社区
 事务模式-AT-图片来自阿里云官网

TCC模式

相比AT模式代理JDBC数据源生成UNDO_LOG来生成逆向SQL回滚的方式,TCC就更简单一点了。

  1. TM向TC注册全局事务,获得XID
  2. RM向TC注册分支事务,然后执行Try方法,同时上报Try方法执行情况
  3. 然后如果收到TC的commit请求就执行Confirm方法,收到rollback则执行Cancel

《我想进大厂》之分布式事务篇(二)-鸿蒙开发者社区
 事务模式-TCC-图片来自阿里云官网

XA模式

  1. TM向TC注册全局事务,获得XID
  2. RM向TC注册分支事务,XA Start,执行SQL,XA END,XA Prepare,然后上报分支执行情况
  3. 然后如果收到TC的commit请求就执行Confirm方法,收到rollback则执行Cancel

《我想进大厂》之分布式事务篇(二)-鸿蒙开发者社区
 事务模式-XA-图片来自阿里云官网

SAGA模式

  1. TM向TC注册全局事务,获得XID
  2. RM向TC注册分支事务,然后执行业务方法,并且上报分支执行情况
  3. RM收到分支回滚,执行对应的业务回滚方法

《我想进大厂》之分布式事务篇(二)-鸿蒙开发者社区
 事务模式-Saga-图片来自阿里云官网

总结

这里从事务的ACID开始,向大家先说了XA是分布式事务处理的规范,之后谈到2PC和3PC,2PC有同步阻塞、单点故障和数据不一致的问题,3PC在一定程度上解决了同步阻塞和单点故障的问题,但是还是没有完全解决数据不一致的问题。

之后说到TCC、SAGA、消息队列的最终一致性的方案,TCC由于实现过于麻烦和复杂,业务很少应用,SAGA了解即可,国内也很少有应用到的,消息队列提供了解耦的实现方式,对于中小公司来说可能是较为低成本的实现方式。

最后再说目前国内的实现框架,云端阿里云的GTS兼容Seata,非云端使用Seata,它提供了XA、TCC、AT、SAGA的解决方案,可以说是目前的主流选择。

 

文章转自公众号:艾小仙

分类
标签
已于2022-6-9 16:41:54修改
收藏
回复
举报
回复
    相关推荐