对账平台设计

背景

随着公司业务的蓬勃发展,交易履约清结算业务的复杂性也在不断的增高,资金以及各种数据的一致性和准确性也变得越发重要。

  • 以交易链路为例,存在着如下一些潜在的不一致场景:

  • 订单支付成功了,但是订单状态却还是"待付款"

  • 物流已经发货了,但是订单上面还是"待发货"

  • 订单用券成功了,但是优惠券状态还是 "未使用"

  • 订单参与活动下单成功了,但是活动没有核销记录

  • ...

上述每个业务场景,都可能产生用户反馈,给用户带来困扰。业务对账平台的核心目的,就是及时发现类似问题,并及时修复。使问题在反馈前即被提前处理。

需求分析

对账的概念随着金融、互联网行业的发展,定义上也经历了几个阶段的变化,如下:

  • stage 1 :对账最初来源于会计核算,是为保证账簿记录正确可靠,对账簿中的相关数据进行检查和核对的工作。
  • stage 2 :随着互联网金融或电商行业的发展,对账也扩大了应用范围,这一时期,对账是指在固定周期内,支付使用方和支付提供方(银行和第三方支付)相互确认交易、资金的正确性,保证双方的交易、资金一致正确。
  • stage 3 :从广义来看,所有的跨端系统之间的数据核对都应该叫对账,主要是检查和发现数据在流转过程中的不一致问题。通常分为信息流的核对和资金流的核对。信息流核对主要是对业务数据之间的核对,资金流是对资金交易数据进行核对。
    想要构建一个通用的业务对账平台,不可避免的要面临以下挑战:

我们对于一个业务对账平台的核心诉求,主要包括要方便业务系统快速接入,要能处理业务方海量的数据,并保证一定的实时性。这会深刻影响业务对账平台的系统设计。

系统分析:

对账流程,可以分解为 "数据加载"、"转换解析"、"数据对比"、"结果处理" 这 4 步。为了适应多样化的业务场景,其中的每一步都需要做到可编排,放置各种差异化的执行组件。在每一个流程节点,需要通过规则可以自由选择嵌入哪个组件。其次,需要把数据从原始格式,转换到对账的标准格式(基于标准格式,就能做标准的通用对比器)。总结起来,我们认为对账引擎需要具备以下的能力:

  • 流程编排能力。

  • 规则能力。

  • 插件化接入能力。

对账数据标准格式:

无论是信息流对账还是资金流对账,我们都可以尝试把对账信息进一步归纳总结,抽取出公共信息字段,组成标椎数据格式,便于对账引擎的设计。

基于此,这里简单设计了一些标准对账字段,如下:

对账标准数据格式,也可以再对账失败时进行落库操作,便于对账告警,自动修复,人工查看等。

对账有一对一,一对多, 多对一 等关系,比对数据主要分为 条目匹配,状态匹配,金额匹配等。raw_data 可以存放此数据,便于对比。

对账方式

对账方式主要分为两种,单向对账和双向对账。

  • 单向对账:以一方数据为基准进行对账。比如结算跟支付平台,以结算数据为基准和支付平台核对,用来发现结算数据为支付成功,支付平台支付失败等问题。
  • 双向对账 :以双方的数据互为基准对账。既要保证结算数据为成功的,支付平台也要成功,又要保证支付平台数据为成功的,结算数据也要成功。
    显而易见,双向对账更能够全面的发现问题。因此在条件允许的情况下,我们会优先选择双向对账。

对账力度

对账粒度也分为两种,分别是明细对账 和总数对账。

  • 明细对账:对双方的每条数据依次进行比对。它的优点是可以准确定位问题数据。缺点是对账口径的设计比较复杂。因为我们需要同时针对漏、重、错三种错误类别设计不同的对账口径,同时还要考虑到业务的边缘场景。稍有不慎,就会影响对账的准确性。
  • 总数对账 :选择一个维度,进行总数级别的对账。总数级别的对账好处是对账口径的设计比较简单,可以快速实现,不易出错。缺点就是无法定位问题数据,一旦对账发现问题。还需要进一步寻找问题数据。
    推荐的做法应该是以明细对账为主,定位具体问题。以总数对账为辅,对明细对账的结果进行复核兜底。

对账时机:

目前对账时机有2种, 一种是离线对账,一种是实时对账。两种模式再系统设计层面非常相似,只有数据加载方式不同,下面介绍两种对账模式的系统流程:

离线对账:

离线对账主要是通过固定的周期进行对账。最短周期为T+1。它的好处是适用性较强,基本可以覆盖所有的对账场景。一些离线定时对账场景,单次对账的数据量可能达到百万级,甚至千万级。这对对账平台的吞吐量造成了挑战。

离线对账有两种方法:

常规方法是,通过数据平台(包含了所有要进行对账的原始主键数据,如订单号)将数据 push 到对账中心的 DB,然后对账中心集群通过分片策略,并按分页分批加载,加载数据进行离线数据对比。

另一种,则是当数据量超过千万时,利用数据平台从 hive 表中获取数据,然后投递到 MQ(kafka)。每个对账服务实例都是一个 Consumer 负责从 MQ 拉取消息消费,这样千万级的数据会变成消息被分散的对账服务器执行。

对账任务一般会选择在业务量较小的凌晨进行,是因为在对账过程中可能会需要通过反查业务接口,来获取实时数据。另一种方案是,对账时不要对业务接口进行反查。但是,会需要对业务数据进行准实时同步,提前进入对账中心的 DB 集群。两者优缺点如下:

结合我们自身业务,我们这里采取的是第一种方式:即由数据平台发送对账数据到 MQ,对账平台通过 MQ 消息反查业务方接口,进行数据对账。

实时对账:

实时对账又可称为 在线对账或准实时对账,往往基于业务消息进行触发,指在事件被触发后的短时间内执行完对账任务。且事件消息触发可能会有高并发,状态易改变等特点,因此需要相应的架构来进行支持。

在线对账和准实时对账的区别主要是在线对账耦合在结算链路中,可以在发现问题数据时,对结算流程进行拦截,而准实时对账是异步进行的,不具备拦截能力。在线对账有一定的局限性,一方面它依赖于对账数据是否能实时的准备好,另一方面也比较占用系统资源。因此我们的做法应该是以周期对账为主,在某些实时性要求比较高,且条件满足的场景使用在线对账。

这里我们主要考虑准实时对账,简单来说就是,通过 监听 业务方 DB 的binlog 日志(或者业务方本身的MQ),投递到 MQ 并进行 binlog 解析,由对账引擎消费 MQ 消息进行对账。

差错处理

差错处理主要是对数据核对过程中发现的问题数据进行处理。可以建立一个统一结构的差错记录,将数据核对发现的问题进行统一存储。差错记录中的数据会进行二次核对,避免由于日切 或者 状态时间差 等原因造成的问题错报。对于那些真实存在问题的数据可以提供两种解决模式,如果是常见的问题,且有一套标准的解决方案的话,可以考虑把它系统化,采取系统自动修复的方式;如果系统无法自动修复,那么我们会进行系统报警,并进行人工处理。

日切,在传统的银行业务中,每日作业需要有一个结束的时间,在该时间之后,需要对当日尚未完成的业务进行集中处理,并盘清当日的业务账目,做好受理下一日业务的所有准备后,即将记账日期更新为下一日。这一过程就叫日切。

系统设计

考虑到 离线对账和实时对账的特点,对账引擎设计需要兼顾这两种类型的对账,现设计对账引擎各个组件如下:

其中 ResourceLoader 、Trigger, Parser 、 Checker 、 ResultHandler 均为标准接口,所有实现了对应接口的 spring bean,都能被编排到对账流程之中,包括业务方自己实现的 plugin。这样就实现了插件化和可编排。每个流程节点的功能如下:

  • ResourceLoader :基于各种数据源(DB、HIVE、RPC、REST 等)提供加载器工厂,加载各个数据源的原始数据。加载的方式支持驱动加载、并行加载、多方加载等方式。业务方也可以自己实现加载器,利用流程编排能力嵌入到对账流程中。

  • Trigger:对账触发器,对账的触发主要依靠触发器,针对不同类型的对账可以编写不同的触发器,常用的触发器可由对账平台提供,如 OrderTrigger(订单触发器),StockTrigger (库存触发器)。

  • Parser :对已加载的原始数据进行建模,转换为对账标准模型。

  • Checker :按照配置对指定字段、按指定规则进行比较,利用规则引擎,提供脚本化化对账方式或者自定义对账插件等。产生对账结果。

  • ResultHandler :使用指定的 handler 对结果进行处理,常见的处理器包括持久化、发送报警、甚至直接修复数据等等。

其中 Config 作为对账平台的配置中心,可以对 对账业务方进行配置,编排,也可提供对账的可视化功能。

实时对账设计要点:

实时对账考虑基于业务MQ消息触发,主要关注 实时性,吞吐量等方面,如消费速率,消息堆积造成实时对账不准确问题。

设计中主要加入了 限流、取样、路由、等 pipeline 来处理高并发事件消息。同时在进入事件处理线程池之前,需要进入阻塞队列,避免大量的请求直接耗尽线程资源,同时实现事件处理的异步化。处理线程批量定时从阻塞队列获取任务来执行。同时,利用延迟阻塞队列,还可以实现延迟对账的特性。出现不一致的情况时,如果立即去进行对比,往往还是不一致的。所以就需要根据情况,在事件发生后的一段时间内,再触发对比

差错处理设计:

在差错处理阶段,可以建立一个统一的差错记录模型,核心字段包括 对账场景、对账批次,数据来源,对账业务ID,错误类型编码,错误原因,数据处理状态 等。通过定时任务定期轮询差错记录的方式发起差错处理流程:首先对差错记录的数据进行二次核对,如果二次核对确认这条数据并没有问题,我们就会回更差错记录的处理状态。如果二次核对发现数据确实有问题。

可以提供两种处理模式。一种是通过系统的手段自动修复。另外一种是通过报警的方式,人为介入。此外可以建立一个问题的人工处理模块。可以对一次结算流程的整个生命周期进行回放,并针对特定场景提供一键修复的能力。

差错处理标准模型
差错处理流程

整体架构图

接入方式

我们提供了一个配置后台可以让用户编写脚本的方式,实现对账。脚本使用了:AviatorScript:https://www.yuque.com/boyan-avfmj/aviatorscript

  • 配置后台
  • 失败明细
相关推荐
HanhahnaH8 分钟前
Spring集合注入Bean
java·spring
未定义.22114 分钟前
电子削铅笔刀顺序图详解:从UML设计到PlantUML实现
java·软件工程·uml
科技在线28 分钟前
科技赋能建筑新未来:中建海龙模块化建筑产品入选中国建筑首批产业化推广产品
大数据·人工智能
雾月5532 分钟前
LeetCode 1292 元素和小于等于阈值的正方形的最大边长
java·数据结构·算法·leetcode·职场和发展
24k小善1 小时前
Flink TaskManager详解
java·大数据·flink·云计算
想不明白的过度思考者2 小时前
Java从入门到“放弃”(精通)之旅——JavaSE终篇(异常)
java·开发语言
时序数据说2 小时前
时序数据库IoTDB在航空航天领域的解决方案
大数据·数据库·时序数据库·iotdb
.生产的驴2 小时前
SpringBoot 封装统一API返回格式对象 标准化开发 请求封装 统一格式处理
java·数据库·spring boot·后端·spring·eclipse·maven
猿周LV2 小时前
JMeter 安装及使用 [软件测试工具]
java·测试工具·jmeter·单元测试·压力测试
晨集2 小时前
Uni-App 多端电子合同开源项目介绍
java·spring boot·uni-app·电子合同