讲讲最大努力通知策略!

来自:打杂的ZRJ(微信号:zrj_guduyan),作者:孤独烟

引言

本文是来填《分布式事务之TCC模型》留下的坑:

  • 服务平台之间的事务性如何保证

OK,现在介绍下业务背景
假设,公司的多个业务部门都需要调第三方支付接口,像下面这样


那么,这么做的缺点很明显!每个部门的项目里都有一段调第三方接口的代码,冗余。因此,我们会将这块抽出来,成立一个为支付服务,像下面这样


这样,各个业务部门对接支付服务就好了。

OK,那么,这个支付服务在通知业务部门支付状态的时候,就必须采用最大努力通知策略来进行设计!

正文

概念

最大努力通知策略:就是尽量去通知,至于通知成功还是失败,无所谓,我不保证!一般会指定一个通知次数,如果超过次数还是失败,那就不通知了,等被通知方主动来查询。
最大努力通知策略只能算是一种跨平台的数据一致性解决方案,适用于一些时间敏感度低的业务,强调的是最终一致性!

实战

先来一张支付时序图,如下图所示


注意看上面的步骤9步骤10,有两次通知的过程。

  • 一次是支付宝通知我们支付系统

  • 一次是支付系统通知业务系统

我们先来看,步骤10,也就是支付系统通知业务系统的过程。
OK.这里要说一下,这个怎么通知呢?
有两种方式,第一种是,通知服务和支付服务在同一台JVM上,如下所示


这种方式,其实很多中小型公司在用。因为对于这类型的公司而言,并没有那么多的订单,这种方式已经能够满足业务需求。
但是呢,这种方式我不细说,因为我想说的是一种更加复杂的情况,也就是通知服务和支付服务在两台JVM上的情形。如下图所示

如上图所示,两个服务之间靠MQ保持一致性。

那么,每个服务具体做什么呢?

支付服务

ok,这个服务在接收到支付宝的通知后,做两个事情

(1)将通知的信息落库
(2)给支付宝回一个"success"的标志位

OK,就这两步先分析一下
如果步骤(1)成功了,步骤(2)失败了呢?
ok,这种情况下,支付宝会一直通知你!直到最大次数!
如果步骤(2)成功了,步骤(1)失败了呢?
ok,这种情况不会发生,因为落库失败直接退出,不能给支付宝发信息。要让支付宝持续通知!

另外起一个线程,扫描落库的表,发送到消息队列中。为什么这么做?请大家阅读《异步服务调用利器(消息队列)》

通知服务

这里一共有三张表

通知规则表:这张表记录了最大通知次数,以及每一次通知间隔的时间。比如:24小时内,按照间隔1min、5min、10min、30min、1h、2h、5h、10h的方式,逐步拉大通知间隔。
通知表:这张表记录了,从消息队列中订阅到的消息,以消息ID作为主键保证幂等性。
通知日志表:这张表记录了每次通知的结果,通知时间,通知地址,通知内容等!

那么,通知服务主要是起一个线程,订阅消息队列,只做一个事情

(1)收到消息后,马上插入通知表。注意幂等性保证!

提问,如果插入通知表失败了怎么办? 你想啊,如果插入通知表失败,消息就丢了啊。去看我的另一篇《分布式之消息队列复习精讲》。简单来说,就是落库完,手动应答消息队列,不能用自动应答模式!这句话看不懂的,可以先去看看消息队列的使用再回头来看看!

(2)另外起一个线程,扫描通知表,根据自己配置的通知规则,解析出通知地址、通知内容,进行通知。注意了,不管成功与失败,都需要将这个步骤中用到的参数以及通知结果插入通知日志表。
通知失败了呢?这里的失败有两种,一种是网络请求失败--请求头得出。另一种是被通知方没有返回成功flag)。
OK,万一失败了,就根据规则表重新计算出,需要过多长时间再发。OK,这里就需要用到《延时任务方案汇总》的知识,推荐时间轮的方案。利用时间轮的原理,过一段时间再次发送,并记录通知日志表。

如果到了最大通知次数,还没通知成功怎么办?
OK,不用管了。等业务方主动来查询。因此,你的支付服务中还有一个查询的接口。可以查询到订单到状态,等业务方自己来查,查完以后业务方自行处理。

支付宝的通知策略

OK,上面说了一大堆讲的是支付系统怎么通知业务系统。现在来说说,支付宝的通知策略,其实也是用最大努力通知策略,在支付宝文档
https://docs.open.alipay.com/203/105286/
中有一句话叫做
程序执行完后必须打印输出“success”(不包含引号)。如果商户反馈给支付宝的字符不是success这7个字符,支付宝服务器会不断重发通知,直到超过24小时22分钟。一般情况下,25小时以内完成8次通知(通知的间隔频率一般是:4m,10m,10m,1h,2h,6h,15h)
我们可以看出,支付宝也使用的是最大努力通知策略。最大通知次数为8。至于他是如何通知的,这估计只有支付宝的员工才知晓了!

推荐↓↓↓
Java编程
上一篇:PYPL 2019年1 月 IDE 榜单:Visual Studio Code 猛追 IntelliJ 下一篇:另一个角度看『异常』