一、概述
咱们今天聊聊分布式事务系列中的最后一个方案:最大努力通知事务。最大努力通知事务的主流实现仍是基于MQ来进行事务控制。最大努力通知事务和事务消息都是通知型事务,主要适用于那些需要异步更新数据,并且对数据的实时性要求较低的场景。
最大努力通知事务主要用于外部系统,因为外部的网络环境更加复杂和不可信,所以只能尽最大努力去通知实现数据最终一致性,比如充值平台与运营商、支付对接、商户通知等等跨平台、跨企业的系统间业务交互场景;而事务消息主要适用于内部系统的数据最终一致性保障,因为内部相对比较可控,比如订单和购物车、收货与清算、支付与结算等等场景。
普通消息是无法解决本地事务执行和消息发送的一致性问题的。因为消息发送是一个网络通信的过程,发送消息的过程就有可能出现发送失败、或者超时的情况。超时有可能发送成功了,有可能发送失败了,消息的发送方是无法确定的,所以此时消息发送方无论是提交事务还是回滚事务,都有可能不一致性出现。所以通知型事务的难度在于投递消息和参与者自身本地事务的一致性保障。
因为核心要点一致,都是为了保证消息的一致性投递,所以最大努力通知事务在投递流程上跟事务消息是一样的,因此也有两个分支:
l 基于MQ自身的事务消息方案
l 基于DB的本地事务消息表方案
二、最大努力通知事务流程
我们先看看事务消息的两个分支:
基于MQ的事务消息
最大努力通知事务在投递之前跟上面流程都差不多,关键在于投递后的处理,因为事务消息在于内部的事务处理,所以MQ和系统是直连并且无需严格的权限、安全等方面的思路设计。
基于事务消息的最大努力通知事务
基于DB消息表的最大努力通知事务
最大努力通知事务在投递之前跟上面流程都差不多,关键在于投递后的处理,因为事务消息在于内部的事务处理,所以MQ和系统是直连并且无需严格的权限、安全等方面的思路设计。最大努力通知事务在于第三方系统的对接,所以最大努力通知事务有几个特性
• 业务主动方在完成业务处理后,向业务被动方(第三方系统)发送通知消息,允许存在消息丢失。
• 业务主动方提供递增多挡位时间间隔(5min、10min、30min、1h、24h),用于失败重试调用业务被动方的接口;在通知N次之后就不再通知,报警+记日志+人工介入。
• 业务被动方提供幂等的服务接口,防止通知重复消费。
• 业务主动方需要有定期校验机制,对业务数据进行兜底;防止业务被动方无法履行责任时进行业务回滚,确保数据最终一致性。
在很多其他资料都会说“业务被动方根据定时策略,向业务活动的主动方进行轮询,进而恢复丢失的业务消息”;但在真实场景中被动方很多时候可能是业务强势方,不会反向调用 业务主动方的接口;所以我们需要一定的熔断探活机制来保证我们的通知有效性。还有很多资料也说“被动方的处理结果不影响主动方的处理结果”,在我的认知中,这句话其实是有缺陷的:在大多数下确实业务被动方的处理结果不影响业务主动方,但在业务被动方确定无法履行业务责任时,业务主动方可能仍需要回滚业务数据。
三、最大努力通知事务 VS 事务消息
最大努力通知事务在我认知中,其实是基于事务消息发展而来适用于外部对接的一种业务实现。他们主要有的是业务差别,如下:
• 从参与者来说:最大努力通知事务适用于跨平台、跨企业的系统间业务交互;事务消息更适用于同网络体系的内部服务交付。
• 从消息层面说:最大努力通知事务需要主动推送并提供多档次时间的重试机制来保证数据的通知;而事务消息只需要消息消费者主动去消费。
• 从数据层面说:最大努力通知事务还需额外的定期校验机制对数据进行兜底,保证数据的最终一致性;而事务消息秩序保证消息的可靠投递即可,自身无需对数据进行兜底处理。
四、总结
最大努力通知事务本质是通过引入定期校验机制来对最终一致性做兜底,对业务侵入性较低;适合于对最终一致性敏感度比较低、业务链路较短的场景。
文章末尾大厂真实面试题以及答案
需要面试资料的小伙伴,麻烦帮忙转发一下这篇文章+关注我,然后添加小助手VX:xuanwo008自取
程序员专属简历模板