场景
A(存在DB操作)、B(存在DB操作)两方需要保证分布式事务一致性,通过引入中间层MQ,A和MQ保持事务一致性(异常情况下通过MQ反查A接口实现check),B和MQ保证事务一致(通过重试),从而达到最终事务一致性。 原理
大事务 = 小事务 + 异步
流程图
流程图 上图是RocketMQ提供的保证MQ消息、DB事务一致性的方案。 MQ消息、DB操作一致性方案:
TransactionCheckListener 是在消息的commit或者rollback消息丢失的情况下才会回调(上图中灰色部分)。这种消息丢失只存在于断网或者rocketmq集群挂了的情况下。当rocketmq集群挂了,如果采用异步刷盘,存在1s内数据丢失风险,异步刷盘场景下保障事务没有意义。所以如果要核心业务用Rocketmq解决分布式事务问题,建议选择同步刷盘模式。
多方事务
当需要保证多方(超过2方)的分布式一致性,上面的两方事务一致性(通过Rocketmq的事务性消息解决)已经无法支持。这个时候需要引入TCC模式思想(Try-Confirm-Cancel,不清楚的自行百度)。 以上图交易系统为例:
如下为A给B转账的例子。
步骤 | 动作 |
---|---|
1 | 锁定B的账户 |
2 | 锁定B的账户 |
3 | 检查A账户是否有1元 |
4 | A的账户扣减1元 |
5 | 给B的账户加1元 |
6 | 解锁B的账户 |
7 | 解锁A的账户 |
以上过程在代码层面甚至可以简化到在一个事物中执行两条sql语句。
和单机事务不同,A、B账户可能不在同一个DB中,此时无法像在单机情况下使用事物来实现。此时可以通过一下方式实现,将转账操作分成两个操作。
步骤 | 动作 |
---|---|
1 | 锁定A的账户 |
2 | 检查A账户是否有1元 |
3 | A的账户扣减1元 |
4 | 解锁A的账户 |
A账户数据发生变化时,发送MQ消息,MQ服务器将消息推送给转账系统,转账系统来给B账号加钱。
步骤 | 动作 |
---|---|
1 | 锁定B的账户 |
2 | 给B的账户加1元 |
3 | 解锁B的账户 |