分布式事务(1)基本概念
分布式事务(2)两阶段提交
分布式事务(3)TCC
分布式事务(4)可靠消息最终一致性
分布式事务(5)最大努力通知
分布式事务【5】最大努力通知
1 最大努力通知的概念
最大努力通知也是一种解决分布式事务的方案:
交互流程:
- 账户系统调用充值系统接口执行充值逻辑。
- 充值系统完成支付处理向账户系统发起充值结果通知;若通知失败,则充值系统按通知策略进行重复通知。
- 账户系统接收到充值系统通知结果完成账户充值逻辑。
- 账户系统未接收到通知会主动调用充值系统提供的接口查询充值结果。
最大努力通知方案的目标: 发起通知方通过一定的通知机制最大努力的将业务处理结果通知到接收方。
1、有一定的消息重复通知机制:因为接收通知方可能没有接收到通知,此时要有一定的机制对消息重复通知。
2、消息校对机制:如果尽最大努力也没有通知到接收方,或者接收方消费消息后要再次消费,此时可由接收方主动向通知方查询消息信息来满足需求。
2 最大努力通知与可靠消息一致性区别?
1、解决方案思想不同
可靠消息一致性:发起通知方需要保证将消息发出去,并且将消息发到接收通知方,消息的可靠性关键由发起通知方来保证。
最大努力通知:发起通知方尽最大的努力将业务处理结果通知到接收通知方,接收通知方有可能消息接收不到,此时需要接收通知方主动调用发起通知方的接口查询业务处理结果,通知的可靠性关键在接收通知方。
2、两者的业务应用场景不同
可靠消息一致性关注的是 交易过程
的事务一致,以异步的方式完成交易。
最大努力通知关注的是 交易后
的通知事务,即将交易结果可靠的通知出去。
3、技术解决方向不同
可靠消息一致性要解决消息从发出到接收的一致性,即消息发出并且被接收到。
最大努力通知无法保证消息从发出到接收的一致性,只提供消息接收的可靠性机制。可靠机制——是最大努力的将消息通知给接收方,当消息无法被接收方接收时,由接收方主动查询消息(消息回查业务处理结果)。
3 解决方案分析
通过对最大努力通知的认识,采用MQ的ack机制就可以实现最大努力通知。
方案1:
本方案是利用MQ的ack机制由MQ向接收通知方发送通知,流程如下:
- 发起通知方将通知发给 MQ。使用普通消息机制将通知发给 MQ。
注意:如果消息没有发出去,可由接收通知方主动请求发起通知方查询业务执行结果。 - 接收通知方监听 MQ。
- 接收通知方接收消息,业务处理完成回应ack。
- 接收通知方若没有回应ack则MQ会重复通知。
MQ会按照间隔1min、5min、10min、30min、1h、2h、5h、10h的方式,逐步拉大通知间隔 (如果MQ采用rocketMq,在broker中可进行配置),直到达到通知要求的时间窗口上限。 - 接收通知方可通过消息校对接口来校对消息的一致性。
方案2:
本方案也是利用MQ的ack机制,与方案1不同的是应用程序向接收通知方发送通知,如下图:
交互流程如下:
- 发起通知方将通知发给 MQ。
使用可靠消息一致方案中的事务消息保证本地事务与消息的原子性,最终将通知先发给MQ。 - 通知程序监听 MQ,接收MQ的消息。
方案1中接收通知方直接监听MQ,方案2中由通知程序监听MQ。通知程序若没有回应ack则MQ会重复通知。 - 通知程序通过互联网接口协议(如http、webservice)调用接收通知方案接口,完成通知。
通知程序调用接收通知方案接口成功就表示通知成功,即消费MQ消息成功,MQ将不再向通知程序投递通知消息。 - 接收通知方可通过消息校对接口来校对消息的一致性。
方案1和方案2的不同点:
- 方案1中接收通知方与MQ接口,即接收通知方案监听 MQ,此方案主要应用与内部应用之间的通知。
- 方案2中由通知程序与MQ接口,通知程序监听MQ,收到MQ的消息后由通知程序通过互联网接口协议调用接收通知方。此方案主要应用于外部应用之间的通知,例如支付宝、微信的支付结果通知。
4 RocketMQ最大努力通知型事务
4.1 业务说明
本实例通过RocketMq中间件实现最大努力通知型分布式事务,模拟充值过程。
本案例有账户系统和充值系统两个微服务,其中账户系统的数据库是bank1数据库,其中有张三账户。充值系统的
数据库使用bank1_pay数据库,记录了账户的充值记录。
业务流程如下图:
交互流程如下:
1、用户请求充值系统进行充值。
2、充值系统完成充值将充值结果发给MQ。
3、账户系统监听MQ,接收充值结果通知,如果接收不到消息,MQ会重复发送通知。接收到充值结果通知账户系
统增加充值金额。
4、账户系统也可以主动查询充值系统的充值结果查询接口,增加金额。
4.2 程序组成部分
本示例程序组成部分如下:
数据库:mysql 5.7.21;包括bank1和bank1_pay两个数据库。
JDK:64位 1.8.0_191
rocketmq 服务端:rocketmq-all-4.8.0
rocketmq 客户端:rocketmq-spring-boot-starter.2.0.2.RELEASE
微服务框架:spring-boot-dependencies.2.1.3.RELEASE、spring-cloud-dependencies.Greenwich.RELEASE
微服务及数据库的关系 :
distribution-tx/dtx-notifymsg/dtx-notifymsg-bank 账户系统1,操作张三账户, 连接数据库bank1
distribution-tx/dtx-notifymsg/dtx-notifymsg-pay 充值系统2,操作充值记录,连接数据库bank1_pay
交互流程如下:
1、用户请求充值系统进行充值。
2、 充值系统完成充值将充值结果发给MQ。
3、账户系统监听MQ,接收充值结果通知。如果接收不到消息,MQ会重复发送通知。接收到充值结果通知账户系统增加充值金额。
4、账户系统也可以主动查询充值系统的充值结果查询接口,增加金额。
4.3 项目源码
源码链接: https://gitee.com/michael_linux/distribution-tx
导入数据库脚本:项目目录\sql\dtx-notifymsg\bank1.sql、项目目录\sql\dtx-notifymsg\bank1_pay.sql。
启动RocketMQ
启动discover-server服务注册中心
导入distribution-tx/dtx-notifymsg/dtx-notifymsg-bank;账户系统:操作张三账户,连接数据库bank1
导入distribution-tx/dtx-notifymsg/dtx-notifymsg-pay;充值系统:操作李四账户,连接数据库bank1_pay
4.4 测试场景
充值系统充值成功,账户系统主动查询充值结果,修改账户金额。
充值系统充值成功,发送消息,账户系统接收消息,修改账户金额。
账户系统修改账户金额幂等测试。
5 最大努力通知小结
最大努力通知方案是分布式事务中对一致性要求最低的一种,适用于一些最终一致性时间敏感度低的业务;最大努力通知方案需要实现如下功能:
- 消息重复通知机制。
- 消息校对机制(消息回查机制)。