这几天看分布式事务相关的知识,网上的信息都是大同小异,但总感觉理解起来比较费劲,不够接地气,所以自己按照自己的理解宏观的总结了一下,因为是纯理论的,没图,看着可能比较累,大家包涵,文章仅代表个人观点,不一定完全正确,如果哪里不对希望大家能评论指正,感激不尽。
无论是单机事务还是分布式事务,其目的都是一样的,就是保证数据的一致性,提交了商品订单就肯定要减少库存也必须扣钱,否则就会有纠纷出现,至于怎么实现数据一致性,那就方法比较多了,单机可以是数据库事务,某些情况可能也可以是触发器,分布式下可以是分布式事务也可以是可靠消息,从这个角度讲现在网络上说的分布式事务解决方案准确来说应该是分布式数据一致性解决方案,毕竟是有了数据一致性的需求才有了事务的解决方案而不是有了事务才保证了一致性。
在数据必须一致的情况下,有两种情况:
第一、高时效性要求
a动作和b动作必须同时完成,比如:订单生成了就一定要同时减库存,否则其他人就还能买,但可能已经没货了,这种情况下只能使用全局事务牺牲性能保证一致性,做法有三种,一是数据库层的XA模式,二是服务层的全局事务管理,像阿里seata的AT模式,三是TCC补偿模式,三种方法的原理在后面讲解
第二、低时效性要求
所谓低时效性要求其实就是a动作和b动作在保持顺序的情况下不严格同时完成(最终一致),比如第三方话费充值,充值申请提交后我并不是特别着急知道成功没成功,差个几分钟不影响啥,只要保证成功了给我把话费加上,不成功的话把钱给我返回来别让我损失就成,这种情况下主要方法也有三种,一是用可靠消息中间件,通过可靠消息保证数据最终一致,二是使用消息中间件和本地消息表,业务处理时不发消息,通过短轮询的方式发送消息,三是使用消息中间件和定时校对的方式,如果接收者处理消息状态没能反馈,发送者主动校对保证一致性,这个又叫最大努力通知,当然最大努力通知一般用在结果反馈上
2PC
两阶段提交协议,顾名思义,就是把原先的一次提交改成了两个阶段,即准备阶段和提交阶段,目的是为了在准备阶段就规避像网络异常、服务异常等情况,增加提交成功率
3PC
把两阶段又扩展了一下,分成canCommit、preCommit、commit,也是为增加提交成功率,很复杂,一般不用
2PC之XA模式
一般说的XA模式指的是支持XA协议的关系型数据库的全局事务模式,事务管理者是数据库,当然如果其他框架支持XA也可以并入这个全局事务,这时候事务管理者就不是数据库而是其他的角色了
2PC之AT模式
与XA类似,事务管理者是独立的服务,更大的一个不同点是回滚方式,通过数据库的逆操作来回滚而不是本地数据库事务回滚,好处是本地事务已提交不占用资源,效率高,为了实现数据库逆操作使用了数据源代理模式来将操作记录在数据库已备回滚
2PC之TCC模式
实现比较麻烦,原理是给每个操作除了实现预备动作,提交动作,还要实现一个回滚动作,就是在业务层面处理回滚,所以灵活性最高,a操作成功b操作失败时只需要调用a操作的回滚动作就可以保证数据一致
可靠消息
由消息中间件保证消息的可靠性,包括消息递送的可靠性、消息存储的可靠性、消息通知的可靠性,保证不会丢消息,如果接收者发生业务异常导致消息不能正常处理,需要发送异常消息给原发送者处理或者人工介入
本地消息表
可以通过本地事务同时处理业务逻辑和在本地保存消息,轮询发送消息到消息中间件,发送成功时在本地修改消息状态,接收者正常处理消息,如果有业务失败情况发送补偿消息,最好再有自动校对功能,接收方处理时应该遵循幂等性原则
最大努力通知
是原先业务的接收方通知发送方结果的一个方案,比如充话费那个,第三方提交后运营商充值,充值完成后通知第三方结果,首先是发消息通知,但消息可能具有可靠性问题,如果第三方长时间没收到回复会主动调用运营商接口查询结果
刚开始是个小商店,货物就在后面的货架上,一个人经营,买东西的人来说要什么什么东西,卖东西的干两件事,收钱和交付商品,两件事是一个人干的,这叫单机系统,很容易保证一致性,后面生意好了店开大了一个人忙不过来了分成两个人,一个人收钱一个人交付商品,在这种场景下我们看各个方案下解决一致性。
全局事务
加入了第三个人,老板娘,老板娘在旁边盯着两个人,看是不是收了钱把货都交了,如果收了钱交货的时候发现没货了就让收钱的把钱退了,不能坑害消费者不然人家投诉甚至砸店呢
2PC
客人来买东西,老板娘先吼一嗓子小王、小李都在不在,两个人如果有一个人不在,对不起生意做不了了您呆会儿再来,两个人都答应了在呢,然后就开始正常交易,交易过程仍然受老板娘监控
XA
原理跟2PC一样,交易失败时,老板娘指挥退钱
TCC
原理跟2PC一样,交易失败时,老板娘不指挥退钱了,而是告诉收钱的人,交付货物失败了,你看着处理下,至于怎么处理,是收钱的人自己负责了,也许他没退钱而是给那个人那个人加在余额里了,下次收钱的时候抵扣呢
可靠消息
科技进步了,买东西不用去实体店了直接网上下单了,收钱的先收钱,收到钱后把交易信息发到公屏上,交付商品的看到公屏上的交易信息准备货物发货,如果发现货物没了,就把缺货的信息发到公屏上,收钱的看到缺货信息,告诉买家,哎对不起没货了您呐,同时把钱给人家原路返回
本地消息表
仍然是线上交易,收钱的收到钱后把交易信息记在本本上就不管了了,加入一个帮手定时去看这个记账本本,然后把信息发到公屏上,后面的流程和可靠消息一样了
最大努力通知
适用于发送者必须知道接收者的处理结果的情况,收钱的人得知道发货成功没有,按正常流程,发货的人把处理结果发到公屏上收钱的看到就行,但是害怕发货的忘了或者什么的没有把结果发到公屏上,这种情况发货的提供了一个自动查询机,收钱的如果等了半天没结果,就自己去自动查询机查一下看发货结果是啥
实现分布式数据一致性的方法有很多,也各有自己的优缺点,不能说哪一种一定好,哪一种一定不好,都要根据自己的实际业务情况来选择,还是那句话,满足业务的实现最简单的就是最好的。