MQ解决通知型分布式事务
1. 通知型事务(MQ)介绍
分布式事务分为柔性事务和刚性事务,而柔性事务主要分为补偿型和通知型,补偿型事务又分:TCC
、Saga
;通知型事务分:MQ事务消息、最大努力通知型。补偿型事务都是同步的,通知型事务都是异步的。
通知型事务的主流实现是通过MQ(消息队列)来通知其他事务参与者自己事务的执行状态,引入MQ组件,有效的将事务参与者进行解耦,各参与者都可以异步执行,所以通知型事务又被称为异步事务。
通知型事务主要适用于那些需要异步更新数据,并且对数据的实时性要求较低的场景,主要包含: 异步确保型事务和最大努力通知事务两种:
- 异步确保型事务:主要适用于内部系统的数据最终一致性保障,因为内部相对比较可控,如订单和购物车、收货与清算、支付与结算等等场景;
- 最大努力通知:主要用于外部系统,因为外部的网络环境更加复杂和不可信,所以只能尽最大努力去通知实现数据最终一致性,比如充值平台与运营商、支付对接等等跨网络系统级别对接;
2. 异步确保型事务
指将一系列同步的事务操作修改为基于消息队列异步执行的操作,来避免分布式事务中同步阻塞带来的数据操作性能的下降。
2.1 MQ事务消息方案
基于MQ的事务消息方案主要依靠MQ的半消息机制来实现投递消息和参与者自身本地事务的一致性保障。半消息机制实现原理其实借鉴的2PC的思路,是二阶段提交的广义拓展。
半消息:在原有队列消息执行后的逻辑,如果后面的本地逻辑出错,则不发送该消息,如果通过则告知MQ发送;
流程
- 事务发起方首先发送半消息到MQ;
- MQ通知发送方消息发送成功;
- 在发送半消息成功后执行本地事务;
- 根据本地事务执行结果返回commit或者是rollback;
- 如果消息是rollback, MQ将丢弃该消息不投递;如果是commit,MQ将会消息发送给消息订阅方;
- 订阅方根据消息执行本地事务;
- 订阅方执行本地事务成功后再从MQ中将该消息标记为已消费;
- 如果执行本地事务过程中,执行端挂掉,或者超时,MQ服务器端将不停的询问producer来获取事务状态;
- Consumer端的消费成功机制有MQ保证;
2.2 异步确保型事务使用示例
举个例子,假设存在业务规则:某笔订单成功后,为用户加一定的积分。
在这条规则里,管理订单数据源的服务为事务发起方,管理积分数据源的服务为事务跟随者。
从这个过程可以看到,基于消息队列实现的事务存在以下操作:
- 订单服务创建订单,提交本地事务
- 订单服务发布一条消息
- 积分服务收到消息后加积分
我们可以看到它的整体流程是比较简单的,同时业务开发工作量也不大:
- 编写订单服务里订单创建的逻辑
- 编写积分服务里增加积分的逻辑
可以看到该事务形态过程简单,性能消耗小,发起方与跟随方之间的流量峰谷可以使用队列填平,同时业务开发工作量也基本与单机事务没有差别,都不需要编写反向的业务逻辑过程
因此基于消息队列实现的事务是我们除了单机事务外最优先考虑使用的形态。