1. 序
数字支付业务是专门和“钱”打交道的互联网金融性质业务,其金融属性决定了在这个业务领域中,技术风险永远是数字支付从业者无法回避的首要技术课题。在所有的技术风险手段中,幂等能力的保障不容置疑占据着重要地位。
幂等,原本是一个计算机学概念,常用于抽象代数中。而在计算机编程领域,幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。反映到到互联网支付业务中,简单理解即“对于同一笔支付交易,多次触发系统的交易执行服务,只能实际执行一次”,以此规避重复的业务处理,避免资损。
当前在国际支付业务全球展业的商业局势下,技术应用部署架构呈现出全球化跨洲多机房部署态势,当同类产品或业务在全球多个机房同时开展时,势必会遇到全球各洲机房之间的数据幂等性保证问题。
如何实现全球幂等,从而保证全球展业的业务幂等,避免幂等击穿带来的资损风险,是国际支付技术团队需要回答的终极问题。
2. 全球幂等资损案例
全球幂等,对于当前的互联网国际支付业务而言,这早已从一种技术风险的场景设想转变为了真实存在的资损案例,在本人工作的支付公司业务展业过程中,今年以来频繁出现的跨洲机房间的业务幂等性击穿让对这一问题的根治提上了日程。
下面举两个真实的全球幂等击穿案例,切实感受一下解决该问题的必要性。
2.1. 案例一:商户跨洲重复下单
商户首次调用US展业区域域名进行支付下单,但此时支付网关出现请求超时情况,返回商户未知结果,此时商户选择采取backup兜底策略,即选择SG展业区域对应域名,使用相同的外部单号发起支付下单请求。
虽然商户首次请求US域名时超时,但服务端系统业务处理并没有中断,实际上US机房系统下单是执行成功的,同时商户请求SG域名同样成功。
由于二次请求和首次请求不在同一个业务机房,SG机房数据库无法感知到US机房数据库存在相同外部单号业务数据,导致业务幂等被击穿,商户同一外部单号成功下单两次,造成了资损风险。
2.2. 案例二:支付网关决策错误
商户在US区域发起扣款请求,网关决策时由于DB抖动,造成决策错误,采取了兜底措施,跨洲路由到SG机房执行扣款,同时由于网络阻塞,网关向商户返回超时异常。此时商户接受到超时反馈,发起重试,此时网络恢复,网关和下游系统正确处理商户请求。
商户首次请求扣款,虽然超时,但是SG机房系统正常处理了扣款,而商户二次请求时US机房系统同样正确处理了扣款。
和案例一一样,两次请求不同的机房导致幂等被击穿,商户扣款了两次,造成了资损问题。
3. 定义全球幂等
上述两个幂等击穿案例本质上都是因为多次请求分别调用的是不同展业区域的业务系统,同时不同区域的机房业务数据由于技术限制或者是合规要求完全存在不互通的情况。而业务数据不互通正是出现跨洲幂等击穿的必要条件。
结合之前分析的真实案例以及其背后的问题本质,我们可以给全球幂等下个定义:对于同一笔业务处理请求,要求其在全球任意地点执行任意次数与执行一次的影响相同。
4. 解决策略
4.1. 回顾幂等发展史
“温故而知新”,在探讨全球幂等问题的解决策略之前,我们先回顾一下幂等的演进史,如下图所示:
- 表级幂等和库级幂等,这两种幂等模式适用于业务数据单库单表部署的数据部署架构,在此部署架构下,幂等数据一定与业务数据位于相同的数据库中。此时,对于幂等能力而言,仅需要解决业务数据的幂等问题即可,即保证业务数据的唯一性。我们可以此称之为业务幂等。
- 机房级幂等, 这种幂等模式主要用于应对业务数据分库分表部署架构的情况,在此部署架构下,由于业务数据的分库分表位可能和幂等数据的分库分表位不一致,导致幂等数据和业务数据不一定同处于相同的数据库之中。如果使用幂等单号,并不能准确的路由到业务数据所在的业务库中,所以此时单纯的业务幂等可能并不能解决机房级别的幂等,需要额外解决业务数据的库表定位问题。而对于此类的问题的常规接解法,是建立一套通用的幂等组件,使用独立的幂等数据库,业务可以借助该幂等组件使用合适的方式实现业务数据的库表定位,例如关联幂等单号和用于分库分表的主键,或者直接关联幂等单号和业务数据的分库分表位。
- 全球幂等, 当业务数据从单域机房的部署升级为全球跨洲多机房部署后,幂等问题进一步复杂化。对于一条业务数据而言,不仅需要回答业务数据的分库分表位,还需要解决业务数据的机房定位问题,并在此基础上实现业务数据无论从哪个机房打入,都能够借助全球幂等进行机房+库表定位,路由至其正确的区域机房之中,这是业务数据在全球化部署架构下进行后续的业务幂等的必要条件。
4.2. 全球数据路由 + 业务幂等
机房级别幂等,目前已有较多的成熟解决方案。目前支付业务技术领域内,较为通用的方案建设一套基础并通用的全局幂等组件,主要用于幂等单号和业务信息的关联关系以独立库的形式进行存储,业务可以借助全局幂等组件实现数据的分库分表路由,并在此基础上自建业务幂等能力,从而解决机房级别的幂等问题。
但常规的全局幂等组件的问题在于没有实现幂等数据全机房同步,仅支持单域机房范围内的数据路由,所以无法在SG展业区域感知到US展业区域的幂等数据。这是当前国际支付业务无法实现全球性的幂等的关键症结所在——幂等数据不支持全机房间数据实时同步。
发掘出关键症结后,解决全球幂等问题的思路就非常清晰了——全球级的数据路由 + 业务幂等。我们需要建设通用的全球幂等组件,主要支持一下两个能力:
- 数据关联,支持幂等数据关联业务信息并独立存储。
- 数据全球同步,支持幂等相关数据的全球机房同步。
全球幂等组件主要解决全球数据的路由问题,而业务只需要在此基础上自建业务级的幂等能力,即可实现全球级的业务展业幂等,从而避免全球性的幂等击穿。
5. 技术路线推演
5.1. 场景化分析
全球幂等组件的整体技术实现上,有哪些关键技术难点需要攻坚?下面通过一个具体场景入手进行分析。
场景: 外部商户使用相同的外部单号现在US发起业务请求,但由于出现业务异常或者其他网络原因,商户选择在SG使用相同的外部单号发起兜底业务请求。
图示分析可以看出,全局幂等的跨机房幂等拦截的必要条件是完成幂等数据的跨洲同步,跨洲同步可能会带来200-300ms跨洲幂等延迟。这里就会引出一个疑问——有没有办法规避跨洲同步带来的幂等延迟?答案是有,但极不推荐,如下图所示:
通过全机房查询幂等数据的方式强行校验幂等性,但对于常态化场景下的200-300ms的幂等校验耗时是业务链路无法接受的。
既然常态化场景下强一致性幂等几乎已然成为一个伪命题,那么能否退而求其次,实现基于最终一致性的两阶段幂等? 答案是可以,具体如下:
- 幂等收敛前:幂等异步检测
- 幂等收敛后:幂等同步拦截
(PS:幂等收敛的时间敞口 = 跨洲传输时间 + 幂等写入时间)
5.2. 设计原则
强一致性的全球幂等是个伪命题, 其带来的幂等耗时是业务链路无法接受的,关于全球幂等组件的一切设计都要建立在这个前提之上。在此前提之上,可以得到的三个设计全球幂等组件原则:
- 最终一致性幂等,幂等需要一定的时间敞口进行收敛
- 同机房幂等场景,可同步拦截
- 跨洲幂等场景,时间敞口收敛前可异步检测,收敛后可同步拦截
对于极端场景的审视需要从业务场景和技术约束多角度切入,如果系统仅仅在极小概率下才可能出现此类极端情况,那么一定程度上可以容忍发生冲突的低概率。如果概率较高,通常表示系统设计上需要重新审视,此时,对于幂等击穿的100%自检测发现可能与运行时拦截一样重要。
于此同时,业务级的幂等也是全球级幂等中的重要一环,当全球幂等组件出现了幂等错误,业务级的幂等也要尽可能的进行兜底。
5.3. 数据同步技术选型
全球幂等组件的关键在于数据全球同步,数据全球同步基建的技术选型上需要满足三个个能力诉求:
- 全球机房部署,支持数据在各个机房可写,可同步
- 支持数据高可用跨洲同步能力,同步延迟短,同步SLA高,以降低跨洲幂等的时间敞口
- 支持数据冲突检测,识别单条数据的多机房写入冲突,以实现时间敞口内的幂等击穿检测
全球幂等的实现依赖于全球多点写且数据双向数据同步的能力支撑,这一点是数据库存储层的库表级别副本同步所无法达成的,所以更优的策略即实现一套应用层面的数据同步应用基建,通过基于任务调度体系的RPC跨机房调用完成数据的灵活同步。
基于数据全球同步基建的技术选型上的三个基本诉求,结合通过应用层同步完成数据全球机房一致的方案,全球应用层数据同步共享基建需要完成以下三点目标:
- 支持数据全球机房可写、双向同步,即全球多点写入
- 支持数据同步的高可用能力,300ms的数据同步SLA为4个9,数据同步成功率的SLA为4个9
- 支持数据多机房间数据写入的覆盖冲突检测和时序控制,不能出现数据写入乱序问题
在满足以上三点目标的基础上,才能保证全球幂等业务能力的可用性和可靠性。
5.4. 技术架构
在明确了整体设计思路,制定的设计原则和完成技术选型后,即可引出全球幂等组件的整体技术架构
6. 后记
在完成整体技术路线推演基础上,技术实现上的问题都是引刃而解的,所以技术实现的细节上不再赘述。
最后再做一点关于这个问题的引申:其实全球性的幂等问题在国际支付业务发展的过程中一直存在,那为什么直到今年这个问题到了“火烧眉毛”的地步上,才决定要启动这个项目呢?
我问过身边不少的人,包括国际支付资深的技术人员,大部分人的口径出奇的一致:“虽然这个问题在过往也出现过,也分析过全球幂等的技术实现,但最终都认为这在技术上是不可能实现的,全球幂等是一个伪命题。”所有人都会举一个极端例子来佐证全球幂等是一个伪命题这个观点——“假如两个请求,携带相同的幂等单号,一个请求US机房服务,一个请求SG机房服务,怎么办?”理论上来说,实时链路在这种极端场景下确实做不到幂等同步拦截,大概率会出现幂等击穿。但每次我听到这个解释后,我都会问一个问题:“在国际支付过往出现的所有全球性幂等击穿案例中,有哪次两个携带相同幂等单号的请求间隔时间是小于跨洲传输时间即200-300ms的极端场景?”我得到的回答都是:“好像没有。” 事实也确实如此。
滑坡谬误, 是一种非形式逻辑谬误,它涉及不合理地使用连串的因果关系,将一系列可能性转化为必然性,从而得出不合理的结论。
在全球幂等是真命题还是伪问题的思辨上,就是一个落入滑坡谬误陷阱很好的案例。当一系列的全球幂等击穿问题摆放在眼前时,许多人在思考解决方案的过程中会由于过分纠结极端场景是否有解而忽略了眼前正在发生的一系列事实问题,就算这个极端场景从来都没有发生过。
这也警示我们业务技术人员在思考问题时一定要结合实际场景进行问题分析,拿出事实证据,不要想当然随机抛一些没有任何依据的观点,从而“捡了芝麻丢了西瓜”。全球幂等是一个伪命题吗?不,“强一致性的全球幂等”是伪命题,但“基于最终一致性的两阶段全球幂等”,不是。
Talk is cheap,show me your proof.