分布式事物
作者:互联网
主流的分布式事物实现方式
两阶段提交
两阶段提交,有一个事务管理器的概念,负责协调多个数据库(资源管理器)的事务,事务管理器先问问各个数据库你准备好了吗?如果每个数据库都回复 ok,那么就正式提交事务,在各个数据库上执行操作;如果任何其中一个数据库回答不 ok,那么就回滚事务。
第一阶段询问,第二阶段执行。
补偿机制 TCC
其实就是程序员自己写代码维护事物回滚和补偿,补偿机制说简单点就是在代码里给出出现问题的补偿机制。我们手动的去补偿出现问题的数据。比如订单调用库存,库存失败了,我们手动回滚订单操作。
一般来说跟钱相关的,跟钱打交道的,支付、交易相关的场景,我们会用 TCC,严格保证分布式事务要么全部成功,要么全部自动回滚,严格保证资金的正确性,保证在资金上不会出现问题。
RocketMQ实现分布式事物(常用)
我们来看看具体的业务场景:用户A转账100元给用户B,这个业务比较简单,我们来分析一下里面具体的步骤:
1、用户A的账户先扣除100元 2、再把用户B的账户加100元
场景一:先扣款后发消息
先扣款再发送消息,万一发送消息失败了,那用户B就没法加钱
场景二:先发消息,后扣款
扣款成功消息发送成功,但用户A扣款失败,可加钱业务订阅到了消息,用户B加了钱
大家应该发现了问题所在,也就是没法保证扣款和发送消息,同时成功,或同时失败;导致数据不一致。
因为上面的问题,RocketMq消息中间件把事物消息分为两个阶段:Prepared阶段和确认阶段
Prepared阶段(预备阶段)
该阶段主要发一个消息到rocketmq,但该消息只储存在commitlog中,但consumeQueue中不可见,也就是消费端(订阅端)无法看到此消息。
commit/rollback阶段(确认阶段)
该阶段主要是把prepared消息保存到consumeQueue中,即让消费端可以看到此消息,也就是可以消费此消息。
整个流程:
- 在扣款之前,先发送预备消息
- 发送预备消息成功后,执行本地扣款事务
- 扣款成功后,再发送确认消息
- 消息端(加钱业务)可以看到确认消息,消费此消息,进行加钱
确认消息说明
注意:上面的确认消息可以为commit消息,可以被订阅者消费;也可以是Rollback消息,即执行本地扣款事务失败后,提交rollback消息,即删除那个预备消息,订阅者无法消费
如果发送预备消息成功,执行本地事务成功,但发送确认消息失败;这个就有问题了,因为用户A扣款成功了,但加钱业务没有订阅到确认消息,无法加钱。这里出现了数据不一致。
RocketMQ回查
RocketMq如何解决上面的问题,核心思路就是【状态回查】,也就是RocketMq会定时遍历commitlog中的预备消息。
因为预备消息最终肯定会变为commit消息或Rollback消息,如果预备消息等了很久还没有通知它发送的话,它会自己去回查本地业务的执行状态,如果发现本地业务没有执行成功就rollBack,如果执行成功就发送commit消息。
标签:阶段,事务,预备,事物,发送,消息,分布式,扣款 来源: https://blog.csdn.net/xs925048899/article/details/104709203