写点什么

支撑好分期千万级还款的支付系统

张修森等人

  • 2022-12-15
    北京
  • 本文字数:3806 字

    阅读完需:约 12 分钟

支撑好分期千万级还款的支付系统

前言

在互联网金融公司开展的业务中,支付系统作为连接金融公司与支付渠道的桥梁,丰富的路由策略支撑、高效的业务处理以及高可用的系统架构都是保证金融公司能为客户提供满意的金融业务的技术保障。

目前在微财的支付系统中,已成功集成了二十余家支付渠道,共计三十余种支付产品;并且支持多种线上支付方式,充分满足了用户不同的支付需求,丰富了用户的支付体验。


然而,面对不同的支付方式以及众多的支付产品,如何在每笔支付请求中快速选取出最优的支付渠道,如何平衡支付成功率和支付渠道成本之间的权重关系,如何保障系统本身的高可用性,如何降低个别渠道异常时造成的支付影响,是支付系统最重要的核心功能。


微财的支付系统能迅速结合渠道可用性、回盘时效、渠道费用以及支付成功率等多个维度,并可在个别渠道不可用时自动降低渠道路由权重,为用户选取出合适的支付渠道进行金融业务的支撑。接下来为大家针对支付系统的核心技术进行介绍。

支付系统的特点


对于当前的支付系统而言,已不再是仅仅满足根据渠道成本、成功率等基本原则来选取最优的支付渠道,而是更多的要综合考虑各个渠道实时的可用性、稳定性以及渠道的自身业务限制,这些场景的兼容能让支付系统为金融业务提供更好的支撑,给用户带来更好的服务体验。


微财在金融业务的支付环节中,将异常场景也纳入了支付路由的路由策略中,对日均千万级的还款进行了很好的业务支撑。


那我们的支付系统是如何在千万级的交易执行过程中,应对渠道异常、系统压力的呢?接下来我们从几个有代表性的功能进行讲解。

系统高可用性保障


因支付系统需要和大量的三方支付渠道对接,支付渠道交互过程出现异常是家常便饭,如何能在支付渠道异常的情况下保证用户支付行为尽可能的不受影响,是我们需要考虑的重要场景。在某个支付渠道出现异常的情况时,降级和熔断是我们常用的一种方式,但其对用户的还款体验会有较大的影响,且无法更精准的缩小其影响范围。因此我们根据支付渠道降级的业务策略来调控某一渠道异常后的路由权重,通过滑动窗口算法来统计和监控渠道某个时间段内异常的比例和绝对数量,达到一定阈值后负反馈给支付路由引擎,在其对支付渠道进行筛选和排序时降低异常渠道的权重,进而调节该异常渠道的使用情况。在降低影响的同时又不会因部分的异常全部关停该渠道的请求,从而达到智能调控的目的。

1. 精准高效的支付路由


为了达到选出最优支付渠道以及提高性能的效果,微财支付系统还设计了一套支持多场景下的渠道选取的路由算法。


渠道决策树算法是以经典的决策树算法作为核心思想结合以路由策略形成的一种渠道路由排序算法。在微财支付系统中,渠道决策树算法会根据支付方式的不同,收集在当前场景下要进行计算的条件作为节点,构建出一个树模型。然后将备选渠道从根节点进入,经由节点的筛选结果流向不同的分支,最终完成备选渠道的排序过程。


我们之所以采用渠道决策树算法对渠道进行排序,是因为其两个优势。其一是节点生成灵活简单,可以根据支付方式的不同定制组合不同的排序条件拼装成一个决策树,并且这种拼装方式是可扩展的,在我们丰富路由策略的时候,可以零代码的方式快捷适配新的策略配置。其二就是高效率的特点,在决策排序过程中,利用其分类和归纳的特点在 O(nlogn)的复杂度下快速获得结果。



渠道决策树算法


渠道路由的策略包含人工配置的一些渠道客观条件,例如业务支持银行信息、支付限额等,也有些是系统根据渠道的表现自动做出的权重策略调整,例如渠道异常后的自动负反馈调节策略,以下是详细方案介绍:

负反馈调节算法主要是监控渠道的健康情况,针对渠道出现异常的情况下,统计异常情况并形成一个指标负反馈给支付路由,达到动态调整渠道权重的目的。其沿用的核心思想来自于 Sentinel 中的一种限流算法滑动窗口算法,它将时间窗口划分为若干个时间片段,每过一个时间片段时间窗口会向右滑动一格,每个时间片段都有独立的计数器。所以统计整个时间窗口的请求数时只需累加所有的时间片段的数据。时间窗口划分的越细,滑动的就越平滑,统计就会越精确。因此,滑动窗口优点是不存在临界值问题,统计精度高,保证统计区间的连续性,渠道异常时可以快速调节等。



负反馈调节算法


举例说明,负反馈调节算法以 10 秒作为统计的时间窗口大小 LeapArray,并配置 5 个样本数 SimpleCount。即对应算法的时间窗口大小为 10 秒,包含 5 个时间片段,每个时间片段的大小为 2 秒,存储的数据记作为指标桶 MetricBucket,其结构为支付渠道+结算主体+支付方式维度的响应数量以及响应异常数量。其应用效果要分两个阶段,其一在渠道路由请求时,要根据当前时间按照窗口时长进行分段,拿到当前时间对应的分段 ID,并取出对应的窗口返回去给对应的统计逻辑进行阈值判断。另外,我们需要在渠道请求的拦截方法中,在得到请求响应后,使用同样的计算方式得到当前时间窗口及时间片段,并通过业务条件判断对 total 和 error 等统计指标进行调整,将数据存入当前时间片段的指标桶。



其中,在渠道路由阶段得到窗口中的统计数据后需要和我们设定的阈值条件作对比,得出当前渠道的健康权重分数。其中我们从两个维度提供了阈值条件:


一种是绝对数量,即在同一时间窗口内若有超过 10 条(该值可通过配置调整)异常的支付请求,则将异常请求的数量 n 除以该时间窗口 10 秒内总订单数量 m 得到结果 y1,乘以其权重基准值 10,得到结果 10y1。


另一种是异常比例,即在同一时间窗口内若有超过 10%(该值可通过配置调整)的异常支付请求,则以同样的方式计算出异常订单比例结果为 y2,乘以其权重基准值 10,得到结果 10y2。


最后通过公式 10-(10n/m)得到最终的系统权值评分,分值越高代表支付渠道的权重越高,排序越靠前。

2. 系统自适应压力调节能力

任何系统都有业务处理的瓶颈上限,如果没法进行精准的压力识别,导致任务并发量或者资源占用明显超过服务器的支撑范围,则会直接影响线上服务的稳定。我们在系统实现过程中,搭建了压力检测服务,通过该服务动态识别机器、组件的运行压力,进行反向调节业务请求速率、并发等限制,以此来达到保护生产服务稳定性的目的。



压力检测技术,支付系统除了自身服务节点以外,还关联了多个组件服务。例如 MySQL、RabbitMQ 等。那如何让系统能自动感知整个支付流程中某个节点出现了性能瓶颈呢?压力指数便是压力检测服务定义的一个性能指标。它不仅包含系统服务节点的压力指标,也包含了系统依赖的组件的一些核心指标。例如服务节点的 JVM 内存、CPU 消耗,MySQL 的连接数、主从同步延迟,RabbitMQ 队列积压量等。压力检测服务通过将以上多个维度的指标通过一定的权重比计算出压力指数,再根据全链路压测结果以及故障演练等方式总结出一个适当的阈值梯度。


压力检测服务计算出的压力指数达到一定的阈值梯度后,会通知支付系统进行限流处理。同时将该指数上报给系统调用方,达到从源头降低压力的效果。当压力指数一直处于高位并保持一段时间后,会触发系统告警,由人工介入排查压力情况是否正常。

3.组件降级提升系统高可用性


在支付系统中采用了 RabbitMQ 作为异步消息组件连通了整个支付流程,我们之所以选用 RabbitMQ 作为消息组件的原因有以下几点:


  1.  保障金融系的稳定性,需要防止消息丢失,要支持消息持久化。

2.  考虑业务的复杂性,需要支持队列的延迟特性。

3.  结合性能和稳定性的综合考量,以及组件的成熟度。


RabbitMQ 在支付系统中起到一个总线的作用,既然这么重要,那就要考虑这个组件出现异常情况下的降级措施。


MQ 是不存储任何数据、没有业务逻辑和复杂性的组件,集成在服务中的主要功能是解耦和削峰。那么替代方案中也需要支持解耦和削峰功能的组件,同时尽量避免增加系统的复杂度。通过多种方案的实践筛选后,我们选取 Redis 作为降级替代组件,在 MQ 异常的情况下,舍弃部分 ack 的机制,用 Redis 的 list 结构作为异步队列进行异步生产和消费,zset 结构作为延迟队列。支付系统在请求 RabbitMQ 发送消息多次重试都失败后,会将消息体存入 Redis 数组中,继续由 Redis 作为替代队列完成消息的生产与消费。同时,为了保证数据的完整性和一致性,我们还需要做到以下几点来完善 Redis 在整个流程中的 MQ 效果:

  • MQ 异常后的快速感知和切换

  • 动态调节 Redis 生产和消费的速率,防止 Redis 内存占用过大

  • 做好消息的幂等消费


目前,支付系统的大部分核心队列以及全部非核心流程队列已经支持 MQ 的故障切换,异常感知和切换时效达到了 3 秒以内,为服务的高可用性提供了保障。

应用现状


当前,微财支付系统已经可以稳定支撑好分期线上每日愈 1500 万笔的支付请求,划扣请求并发可达 2000+。当然,这只是基于当前业务量级的场景下,结合服务资源占用以及性能支撑的考量得出的综合指标。在未来流量激增的情况下,我们可以通过横向扩充节点以及自动压力调节和主动降级等方式将支付处理能力快速提高 5-10 倍的水平。


另外,通过压力检测技术、组件降级等方案,支付系统可以在个别渠道异常或组件异常者的情况下,采用自动降低异常渠道权重,限流降级等方式最大限度降低渠道异常对支付系统及用户还款的影响,全面保障系统的高可用性。截至当前,支付系统的最高可用性已经达到 99.9%以上,用户支付成功率提升了 30%,渠道异常降级触发达 40 余次,成功避免了上百万笔还款支付因渠道异常导致的失败,稳定支撑微财数百万用户的千万级线上还款操作。

 

本文作者:

张修森,微财数科高级工程师

赵伟伟,微财数科高级工程师

周正杭,微财数科资深工程师

曹倩倩,微财数科工程师

李军,微财数科技术总监

吴迪,微财数科产品技术负责人


2022-12-15 11:505274

评论

发布
暂无评论
发现更多内容

架构训练营模块一作业

老实人Honey

架构实战营

如何优雅的实现一个Client

Apologize

Java 设计模式 代码设计 client

登录验证那些事儿

江湖一点雨

Token Cookie JWT session处理方案 单点登录

支点交易所APP系统开发介绍

如何让孩子晚上八点前写完作业的

Ian哥

作业

Linux之文件属性详解

入门小站

Linux

ARTS 日常打卡 - 7

pjw

架构之:serverless架构

程序那些事

系统架构 软件架构 架构设计

Structured Concurrency for C

实力程序员

代理

卢卡多多

代理 代理原理 7月日更

Xshell 如何导入 PuTTYgen 生成的 key

HoneyMoose

Rust 与 Golang - 何时使用它们?

吴脑的键客

rust Go 语言

NFT卡牌挖矿钱包系统软件开发方案

如何设计财务对账系统 —— 从0到1搭建对账系统实战

蒋川

支付系统 对账系统 财务对账系统 财务审核系统

从0到1:用脚做一个路由器漏洞实例

网络安全学海

运维 网络安全 信息安全 渗透测试· SQL注入

Reactive Spring实战 -- 响应式MySql交互

binecy

MySQL 响应式编程 Reactive Spring

用太极拳讲分布式理论,真舒服!

悟空聊架构

分布式 事务 CAS Base 7月日更

一篇并不起眼的Kafka面试题

王知无

RFX币挖矿系统软件开发简介

Rust从0到1-智能指针-RefCell<T>

rust 智能指针 smart pointer RefCell<T>

打通“任督二脉”:Android 应用安装优化实战

vivo互联网技术

android 打包APK so文件

【LeetCode】三数之和Java题解

Albert

算法 LeetCode 7月日更

蚂蚁矿池系统软件开发方案

Flink生产环境TOP难题与优化,阿里巴巴藏经阁YYDS

王知无

两天搞定一个BUG

IT蜗壳-Tango

7月日更

【Flutter 专题】88 初识状态管理 Bloc (三)

阿策小和尚

Flutter 小菜 0 基础学习 Flutter Android 小菜鸟 7月日更

我被InfoQ写作平台签约啦

xcbeyond

程序人生 签约计划

共1575道,内卷把我逼成“收集王”汇总十家大厂面试题后,产出Java“完美圣经”

Java架构师迁哥

在线ASCII流程图编辑器工具

入门小站

工具

🏆【SpringBoot技术专题】「Cache缓存组件」Redis缓存使用技巧及注解大全

洛神灬殇

redis cache Sprint Boot 7月日更

松华说|如何快速熟悉和上手业务

松花皮蛋me

支撑好分期千万级还款的支付系统_架构_InfoQ精选文章