背景&问题
随着美团外卖配送事业的蓬勃发展,配送清结算业务的复杂性也在不断的增高,总结起来,主要有以下几个特点:
场景多:包括专送、众包、快送、跑腿、外部单等多条业务线;订单补贴、活动发放、奖惩、餐损、打赏、保险等多种结算场景;对接外部十多个系统。
链路长:清结算内部经历定价、记账、汇总账单、付款等多个流程。
单量大:目前日单量已达到千万级别。
在这样的业务背景下,我们的系统可谓险象环生。因业务高度复杂,稍有不慎就会出现问题,面对千万级的日单量,同时还要确保结算金额的准确,这就让我们对问题的容忍度变得极低。这也给我们的资金安全保障造成了巨大的挑战。下面我们列举了一些系统日常运行过程中出现的问题。
对账的定义
对账的概念随着金融、互联网行业的发展,定义上也经历了几个阶段的变化,如下:
stage 1 :对账最初来源于会计核算,是为保证账簿记录正确可靠,对账簿中的相关数据进行检查和核对的工作。
stage 2 :随着互联网金融或电商行业的发展,对账也扩大了应用范围,这一时期,对账是指在固定周期内,支付使用方和支付提供方(银行和第三方支付)相互确认交易、资金的正确性,保证双方的交易、资金一致正确。
stage 3 :从广义来看,所有的跨端系统之间的数据核对都应该叫对账,主要是检查和发现数据在流转过程中的不一致问题。通常分为信息流的核对和资金流的核对。
信息流核对:主要是对业务数据之间的核对。
资金流核对:是对资金交易数据进行核对。
系统概况(美团)
配送结算做为核心交易履约系统,上游对接了订单、奖惩、活动等十多个外部系统,下游又承担了对接支付平台、财务系统的职责,不仅“承上启下”,而且涉及业务复杂。而系统内部又历经定价、计费(清算)、记账、汇总账单、付款等多个环节,系统的高度复杂性给对账的全面性和准确性造成了极大的困难,如图:
设计思路
从整体来看,按照时序维度的先后,系统对账主要分为三阶段的工作。分别是数据准备、数据核对和差错处理。在对账专业概念中,数据核对和差错处理又叫轧账和平账。三个环节紧密相连,从前期准备、问题发现、问题处理三个角度展开对账工作。
数据准备
数据准备,顾名思义,我们需要把对账所需的全部数据,接入到我们的对账系统。该模块主要实现两个目标:
第一是为不同的外部系统提供多元化的接入机制
第二是通过数据适配的手段把外部数据以统一的格式进行转换和存储
在数据接入层,我们会针对不同的数据接入方提供三种不同的数据接入模式。
数据拉取:我们主动拉取数据,并通过数据适配的方式,将数据存储到对账数据池中
数据推送:由数据接入方将数据通过ETL(Extract-Transform-Load)等方式直接推送到我们的对账数据池中,数据格式由数据接入方自行适配
文件上传:我们会提供标准的文件模板,由数据接入方填充数据,通过文件上传的方式将数据接入到我们的数据池
其中第二种方式是我们最优选择的,因为数据推送这种形式对于数据接入方来说只需要一次性编写相关的代码,定期运行,一劳永逸,减少了人工上传的成本。对于我们结算来说,也不需要感知对方的数据格式以及业务逻辑。
数据核对(轧账)
数据核对是对账中最核心的一个阶段。其目标是发现问题数据。数据核对阶段我们的两个目标是保障数据核对的覆盖度和准确性。经过总结和梳理,数据核对过程可以分为以下5个环节。
1. 问题梳理
由于数据核对的目标是发现问题,那么我们进行数据核对就要从问题出发,首先明确我们要通过对账发现哪些问题,只有这样才能保证数据核对的覆盖度。经过梳理,我们发现在数据流转中过程中数据的不一致问题可以统一归结为三类,分别是漏结、重复结、错结。我们可以从这三个角度去统一进行问题梳理。下面介绍一下这三种错误类型的具体含义。
·漏结:发起方有数据,而接收方没有数据。
·重复结:接收方重复处理,或发起方同一条数据请求了两次。
·错结:发起方和接受方数据不一致。一般会发生在金额和状态两个字段。
2. 对账方式
对账方式主要分为两种,单向对账和双向对账。
单向对账:以一方数据为基准进行对账。比如结算跟支付平台,以结算数据为基准和支付平台核对,用来发现结算数据为支付成功,支付平台支付失败等问题。
双向对账:以双方的数据互为基准对账。既要保证结算数据为成功的,支付平台也要成功,又要保证支付平台数据为成功的,结算数据也要成功。
3. 对账粒度
对账粒度也分为两种,分别是明细对账和总数对账。
明细对账:对双方的每条数据依次进行比对。它的优点是可以准确定位问题数据。缺点是对账口径的设计比较复杂。因为我们需要同时针对漏、重、错三种错误类别设计不同的对账口径,同时还要考虑到业务的边缘场景。稍有不慎,就会影响对账的准确性。
总数对账:选择一个维度,进行总数级别的对账。(订单总数或金额总数)总数级别的对账好处是对账口径的设计比较简单,可以快速实现,不易出错。缺点就是无法定位问题数据,一旦对账发现问题。还需要进一步寻找问题数据。
因此,推荐的做法应该是以明细对账为主,定位具体问题。以总数对账为辅,对明细对账的结果进行复核兜底。
4. 对账口径
对账口径,也就是具体的对账逻辑的设计。我们会提供固定的对账模板,供不同的对账场景选取。如果某些特殊场景对账模板不能覆盖,也可以采取对账逻辑自定义的方式进行对账。
经过总结我们发现,对账的形式无非就是两方比对和自身异常检测两种。两方比对又可以细分为一对一、多对一、一对多。比对方法也主要是分为条目匹配和金额匹配。自身异常检测主要是重复性和异常状态的检测。我们把这些通用的对账逻辑模板化,减少重复的开发工作。
5. 对账时机
数据核对的最后一步就是对账时机的选择。分为离线对账和在线对账。
离线对账:主要是通过固定的周期进行对账。最短周期为T+1。它的好处是适用性较强,基本可以覆盖所有的对账场景。
在线对账:又分为实时对账和准实时对账。实时对账和准实时对账的区别主要是实时对账耦合在结算链路中,可以在发现问题数据时,对结算流程进行拦截,而准实时对账是异步进行的,不具备拦截能力。在线对账有一定的局限性,一方面它依赖于对账数据是否能实时的准备好,另一方面也比较占用系统资源。因此我们的做法应该是以周期对账为主,在某些实时性要求比较高,且条件满足的场景使用在线对账。
差错处理(平账)
差错处理主要是对数据核对过程中发现的问题数据进行处理。我们会建立一个统一结构的差错记录,将数据核对发现的问题进行统一存储。差错记录中的数据会进行二次核对,避免由于日切等原因造成的问题错报。对于那些真实存在问题的数据我们会提供两种解决模式,如果是常见的问题,且有一套标准的解决方案的话,我们会把它系统化,采取系统自动修复的方式;如果系统无法自动修复,那么我们会进行系统报警,并进行人工处理。
对账系统设计实现
总体架构
综上所述,对账体系的整体架构,分为三个模块,分别是离线对账平台,在线对账平台和平账中心。完全是按照我们上面的对账思路设计的。三个模块互相协作,一体化的完成数据准备、数据核对、问题处理三部分工作。由于我们整个清结算系统是围绕不同的费用项建立的,因此费用项也是我们设计对账、执行的对账一个最小粒度的单元。
具体介绍下三个模块:
离线对账模块
离线对账分为三个子模块,分别是数据接入层、对账管理层和对账执行层。
在数据接入层我们提供拉取和推送两种模式,经历一个数据适配的过程,将数据存储到我们统一的对账数据池当中。
在对账管理层当中,我们抽象出了一个对账场景的概念,我们基于对账场景进行对账属性的配置:首先要选取对账双方的数据源;然后进行对账口径编辑,这里提供了自定义和模板选择两种方式;最后配置对账的周期。这里我们是通过cron表达式来进行周期配置的。
在对账执行层,我们会拉取对账数据池和对账核心配置中的相关数据,经历配置解析,数据抽取,策略执行的过程,最终输出对账结果。
在线对账模块
下图左边是在线对账平台的架构图,右边是在线对账的实例。我们通过RPC、监听消息队列(MQ)、监听数据库binlog三种方式进行对账接入。在线对账平台分为管理层和执行层。管理层主要是承担策略编辑、策略绑定和拦截管理的相关工作。而执行层分为异步(准实时)对账和同步(实时)对账两个模块。
右边两图分别是分别是异步对账和同步对账的实例。在异步对账的实例中,是运单和结算单元的对账。
运单是什么?对应外卖订单,作为配送内部的基础交易数据。
结算单元是什么? 清结算系统内部的模型,和运单是一对一关系,记录运单各个节点的结算状态。
①异步对账:我们分别监听运单和结算单元的Binlog,通过Kafka->Storm的经典架构,进行对账策略的执行。实际的流程比较复杂,这里只是一张简图,大概就是:(细节可以忽略)
收单运单消息后,我们会把对于的运单以List的形式存储到Squirrel(Redis)中,当结算消息来了以后,就把对应运单记录Delete掉。如果有运单记录一直停留在List当中,也就是说明结算消息没有来,应该是发生了漏结算。我们通过过定时任务轮询运单List将问题数据输出。
②同步对账:示例中是结算内部的流程,经历结算单、账单、付款几个流程。因为付款是最后一个流程,如果这个时候数据存在问题,那么就会造成实际的资金损失。因此我们会在付款环节之前,对前面的数据进行对账。如果发现账单和结算单的数据不一致,我们就会进行数据拦截。
差错处理模块
在差错处理阶段,我们会建立一个统一的差错记录模型,核心字段包括对账场景、对账批次,数据来源,错误类型编码和数据处理状态等。通过定时任务定期轮询差错记录的方式发起差错处理流程:首先对差错记录的数据进行二次核对,如果二次核对确认这条数据并没有问题,我们就会回更差错记录的处理状态。如果二次核对发现数据确实有问题。我们会提供两种处理模式。一种是通过系统的手段自动修复。另外一种是通过报警的方式,人为介入。此外我们还建立了一个问题的人工处理模块。可以对一次结算流程的整个生命周期进行回放,并针对特定场景提供一键修复的能力。
小结与展望
按照计划实施后,系统的各个节点都会有行之有效的对账手段覆盖,实现资金安全、数据一致性的保障,示意图: