"分布式事务"解决方案汇总 -- 2PC/TCC/事务消息/1PC

说到分布式事务,网上的文章汗牛充栋,理论很多,实践也多。有的清晰的说明了问题,有些越看越糊涂。 
之前我也写过一篇分布式事务的文章《分布式消息队列RocketMQ–事务消息–解决分布式事务的最佳实践》,里面主要讲了“事务消息”这1种解决方案的2种实现方式。本文将在那篇文章的基础上,把我认为的其他靠谱方案也系统性的整理一下。

2PC的问题

2PC简介

说到分布式事务,就会提到2pc。2pc是什么,我这里简要说明一下。网上文章实在太多。就不画图详细阐述了。

2pc涉及到2个阶段,3个操作: 
阶段1:“准备提交”。事务协调者向所有参与者发起prepare,所有参与者回答yes/no。 
阶段2:“正式提交”。如果所有参与者都回答yes,则向所有参与者发起commit;否则,向所有参与者发起rollback。 
因此,要实现2pc,所有参与者,都得实现3个接口:prepare/commit/rollback。

2PC的实现

关于2pc,对应的实现层面,也就是XA协议。有一个Atomikos开源库,也实现了这个协议。有兴趣的可以去看一下如何使用。

2PC的问题

(1)阶段2,事务协调者挂了,则所有参与者接受不到commit/rollback指令,将处于“悬而不决”状态 
(2)阶段2,其中一个参与者超时或者出错,那其他参与者,是commit,还是rollback呢? 也不能确定

为了解决2pc的问题,又引入3pc。3pc有类似的挂了如何解决的问题,因此还是没能彻底解决问题,此处就不详述了。

TCC

为了解决SOA系统中的分布式事务问题,支付宝提出了TCC。2PC通常都是在跨库的DB层面,而TCC本质就是一个应用层面的2PC。

同样,TCC中,每个参与者需要3个操作:Try/Confirm/Cancel,也是2个阶段。 
阶段1:”资源预留/资源检查“,也就是事务协调者调用所有参与者的Try操作 
阶段2:“一起提交”。如果所有的Try成功,一起执行Confirm。否则,所有的执行Cancel.

TCC是如何解决2PC的问题呢?

关键:Try阶段成功之后,Confirm如果失败(不管是协调者挂了,还是某个参与者超时),不断重试!! 
同样,Cancel失败了,也是不断重试。这就要求Confirm/Cancel都必须是幂等操作。

下面以1个转账case为例,来说明TCC的过程: 
有3个账号A, B, C,通过SOA提供的转账服务操作。A, B同时分别要向C转30, 50元,最后C的账号+80,A, B各减30, 50。

阶段1:A账号锁定30,B账号锁定50,检查C账号的合法性(比如C账号是否违法被冻结,C账号是否已注销。。。)。 
所以,对应的“扣钱”的Try操作就是”锁定”,对应的“加钱”的Try操作就是检查账号合法性

阶段2:A, B, C都Try成功,执行Confirm。即A, B减钱,C加钱。如果任意一个失败,不断重试!

从上面的案例可以看出,Try操作主要是为了“保证业务操作的前置条件都得到满足”,然后在Confirm阶段,因为前置条件都满足了,所以可以不断重试保证成功。

事务消息 – 最终一致性

关于最终一致性,又有2种实现方式,这个在《分布式消息队列RocketMQ–事务消息–解决分布式事务的最佳实践》中已经有详细阐述,此处不再展开。

1PC – Saga – 事务补偿

我们知道,在tcc里面,有2个阶段。其中第1个阶段是“锁定资源”,目的是为了保证第2个阶段的提交在业务上不会失败。 
而1pc,就是舍弃掉第1个阶段,不做资源锁定,直接进行第2个阶段的提交!如果业务的特性可以允许不需要锁定资源,那就可以省去第1个阶段,直接做第2个阶段。

如果第2个阶段失败呢,有2种策略:策略1,同TCC一样,也是不断重试commit,硬着头皮上;策略2,回滚,也就是事务补偿,做之前操作的反操作。

关于1pc,个人理解的不是特别到位,有兴趣的可以参考cqrs的saga。 

推荐一个交流学习群:650385180里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多:

Spring Boot 2.0已发布,来聊聊它的新特性。

猜你喜欢

转载自my.oschina.net/u/3778089/blog/1630054