浅谈分布式事务

事务就是一个会话过程中,对上下文的影响是一致的,要么所有的更改都做了,要么所有的更变都撤销掉。就要么生,要么死。没有半死不死的中间不可预期状态。
分布式事务,常见的两个处理办法就是两段式提交(2PC)和补偿。
两段式提交典型的就是XA,有个事务协调器,告诉大家,来都准备好提交,大家回复,都准备好了,然后协调器告诉大家,一起提交,大家都提交了。

补偿比较好理解,先处理业务,然后定时或者回调里,检查状态是不是一致的,如果不一致采用某个策略,强制状态到某个结束状态(一般是失败状态),然后就世界太平了。典型的就是冲正操作。
准备好了以后,如果没有问题,收到提交,所有人都开始提交。
这个时候,比如对数据库来说,有redo日志的。
如果某个数据库这时候宕机了,那么它重启的时候,先执行检查,也会把上一次的这些操作都提交掉的。所以各个点的数据都是一致的。
 
问题 1:比如 一个业务要调用很多的服务都是写操作,如果有其中一个写的服务失败了,怎么办 ?假设 4个写的吧,有2个写失败了 。

淘宝之类的网站一般的做法是,如果4个都成功才算成功,那么这次提交时4个写都设置成一个中间状态,先容许不一致。然后4个执行完成了以后,回调或是定时任务里检查这4个数据是不是一致的,如果一致就全部置为成功状态,如果不一致就全部置为失败。
 
复杂的业务交互过程中,不建议使用强一致性的分布式事务。解决分布式事务的最好办法就是不考虑分布式事务。就像刚说的问题一样,把分布式的事务过程拆解成多个中间状态,中间状态的东西不允许用户直接操作,等状态都一致成功,或者检测到不一致的时候全部失败掉。就解耦了这个强一致性的过程。
 
一般情况下准实时就成了。涉及到钱,有时候也可以这么搞。
淘宝几s内完整一个订单处理,不是什么问题吧。
银行也不是全部都强一致性。也会轧账和冲正。
特别是涉及到多个系统的时候,我们比如买机票,支付完成以后,只支付完成状态,然后返回给用户了,我们过几分钟再刷新页面,才会看到变成已出票,订单完成状态。
这个时候,如果我们要求所有处理,都是强一致性的,那么久完蛋了。页面要死在那儿几分钟,才把这个事务处理完成,返回给用户。
 
这样就肯定涉及一个问题,支付了,但是最终出票没出来。那就没办法,商量换票或退款。
淘宝的订单改成出票失败,给支付发消息通知退款。
慢的时候,有可能是手工出票,这时出一张票半小时都可能,如果要求都必须强一致性的话,所有处理线程都挂在哪儿,系统早就完蛋了。
 
解决分布式事务的最好办法就是不考虑分布式事务。
拆分,大的业务流程,转化成几个小的业务流程,然后考虑最终一致性。
 
问题2:分布式事务是自己开发还是用一些中间件?
 
1、只要一个处理逻辑能保证要么成功,要么跟什么也没做一样,都算是事务。数据库事务,MQ也有事务。
你自己甚至可以写个程序生成两个文件,要么都生成了,要么都删掉不留痕迹,这也算是事务。
2、分布式事务这一块有个XA规范,实现XA接口的事务,都可以加入到一个分布式事务中,被XA容器管理起来。
3、补偿的办法,需要具体情况具体分析,没有一个各种场合都适用的框架。

标签: 分布式事务