![](http://static.blog.csdn.net/images/category_icon.jpg)
版权声明:本文为博主原创文章,未经博主允许不得转载。
说到分布式事务,网上的文章汗牛充栋,理论很多,实践也多。有的清晰的说明了问题,有些越看越糊涂。
之前我也写过一篇分布式事务的文章《分布式消息队列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。
http://www.cnblogs.com/netfocus/p/3149156.html
-
顶
- 0
-
踩