对账的重要性/作用
支付对账系统是整个支付清结算体系中具体基础性意义的一个环节,是确保支付平台与各类第三方支付渠道数据一致性的关键系统,是商户资金结算、资金划拨、资金报表等逻辑准确运行的重要前提。//对账成功,才结算给下游。
考虑完成对账、以及后面会涉及的处理差错,其结果都是产生对账明细数据,而对账明细数据是渠道vs平台后最为准确的资金数据,对于后续的商户清分、资金清算、结算都具有重大意义,所以复杂查询的频率会比较高,并且数据的使用时间范围也比较大,对于交易量比较大的公司一年的支付数据量可能达到数十亿规模,在数据存储方面,可以考虑采用TIDB这类分布式关系型数据库来存储对账结果相关的数据,这样后续的数据处理逻辑效率会提高很多。可能有人会问为什么不直接使用Hive进行查询,这是因为Hive的单条查询和批量查询的效率是一样的,所以并不太适合实时查询,而如果需要将对账、结算等数据通过管理系统进行管理,涉及的查询场景比较多,所以综合考虑使用分布式关系型数据库会更合适一些。//对账成功结果表,是最准确的数据
总结
一句话,只有对账成功了的订单数据,才结算给下游。
对账时间
每天凌晨左右对账。//反正不管是哪个时间节点,对的都是前一天。
对账字段
对账文件中包含的主要信息有:商户订单号、交易流水号、交易时间、支付时间、付款方、交易金额、交易类型、交易状态这些字段。
对账核心步骤
大概的流程其实是很简单的,总共只有几个核心的步骤。具体实现的话,又是另外一回事了,特别是如果要引入第三方开源大数据软件的话,继续用学习新的东西,并且应用到实际项目中去。
工作使用
本地数据库使用主还是备库?
备库。避免拖垮主库。
数据量不大
直接在内存里比较数据字段是否相等。
独立的对账系统-微服务
远程数据的数据源?
1.下载对账单接口
微信 支付宝 //数据源把数据库数据读取到对账文件,然后供下游下载
2.ftp服务器
单向对账和双向对账
对账方式
对账方式主要分为两种,单向对账和双向对账。
1.单向对账:以一方数据为基准进行对账。比如结算跟支付平台,以结算数据为基准和支付平台核对,用来发现结算数据为支付成功,支付平台支付失败等问题。 2.双向对账:以双方的数据互为基准对账。既要保证结算数据为成功的,支付平台也要成功,又要保证支付平台数据为成功的,结算数据也要成功。
显而易见,双向对账更能够全面的发现问题。因此在条件允许的情况下,我们会优先选择双向对账。
对账方式
1.单向对账:一般拿第三方支付机构或银行流水,与自己系统进行对账,防止出现掉单问题;
2.双向对账:两个应用间的流水进行双向核对,如订单与财务系统,既要保证财务系统支付成功的记录,订单系统也是成功的;也要确保订单系统记录成功的记录,财务系统也成功。
我们一般采用双向对账的方式进行对账。
还是不明白双方对账是指什么?待补充。
如何对账/解决方案
作者:yangkai 网址:ykblog.top 来源:YK Blog 著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
具体对账的方法有多种,比如:
1.sql核对 //数据量小,百万级别以下 exist insert select 最简单的方式,也是问题比较多方式,对数据库压力比较大,数据特别多的时候,对账效率比较低。
2.redis核对 //数据量中,百万级别以上,引入缓存中间件 set集合分别diff (inter)上游、下游数据 比较好的方式,可以降低数据库压力,redis方便根据数据量做水平扩展。
3.sprak核对 //数据量,千万级别到亿级别,引入大数据中间件 采用流式运算进行比对;(具体做法待扩展)
异常数据
1.扎帐 找出有问题的订单,叫扎帐。
2.平账 处理有问题的订单,叫平账。 即数据不相等,怎么处理?
处理对账相关的问题 1.不同系统日切点不一致问题:滚动对账 //因为日切点导致的订单,可以再延后一天对账,也就是说今天对账包括昨天之前的日切点漏电的订单。 2.差错处理:补账,补偿(退款)//如果上游未支付成功,那么要退款。如果上游支付成功,那么更新支付状态为成功。
6、差错处理在一般系统中,差错处理分为两种,一种人工来处理,一种系统自动来处理。主要有如下情况:本地未支付,支付渠道已支付。这主要是本地未正确接收到渠道下发的异步通知导致。 一般处理是将本地状态修改为已支付,并做响应的后续处理,比如通知业务方等。本地已支付,支付渠道已支付,但是金额不同,这个需要人工核查。本地已支付,但是支付渠道中无记录;或者本地无记录,支付渠道有记录。在排除跨日因素外,这种情况非常少见,需要了解具体原因后做处理。
作者:AskHarries 链接:juejin.cn/post/684490… 来源:掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
#不同交易量 不同解决方案 支付对账涉及账单下载处理、核心对账、差错处理等诸多细节逻辑,同时根据交易量大小的不同,需要处理的数据量规模也不尽相同,需要在数据处理时进行一些比较细致地思考。在本文中,作者以单渠道日成功交易订单量300W左右规模为背景,以较少的系统资源占用为目标,给大家介绍下系统的实现细节。同时,对于数据不断增长的情况下,支付对账系统该如何演进,作者也会结合自身的实践与思考与大家一起交流探讨!
对账时可以优化的点
在了解到对账的逻辑后,那么在具体进行系统编码时应该如何处理呢?
按照上述逻辑,我们需要将账单数据表与支付平台订单表进行full join,但是由于账单表我们是存储在Postgresql上的,而支付系统所采用的数据库可能是Mysql或Oracle,总之,从系统拆分的角度看,一般是不会将对账处理与在线支付订单放在一个库中的,即便在一个库直接关联账单表与支付订单表也是不明智的,一方面这样可能会影响实时支付系统的稳定性,另外这些表的数据都是不断增长的,随着数据的积累会也会导致对账数据查询变慢。
所以,在进行某个渠道对账时需要根据条件将账单数据、支付平台订单数据分别清洗到两张中间表中,分别叫做账单待对账中间表(A表)、订单待对账中间表(B表),然后通过这两张表进行full join操作,这样可以确保对账逻辑不影响别的业务,同时这部分数据可以在日终完成对账任务后定期清理掉,确保中间表数据规模处于可控状态。
在代码层面通过A表 full join B表后,会得到一个结果集,如果这个结果集数据比较大,系统没有采用Spark+Hive这种方式话,通过传统编程方式则需要对查询进行分页,考虑到数据逐条对账处理速度较慢,可以一页获取数据条数稍多一些,例如一次取5W条,然后在系统内部采用多线程方式对数据集分割后并行处理,每个线程按照特定的对账逻辑执行,得到对账明细结果集或差错结果集后,批量存入对账数据库。
1.数据库 备库可能用于读,所以为了彻底不影响,使用中间表(临时表)。中间临时表会定时删除。
2.full join
3.分页
4.多线程
发展趋势
系统演进化方向
对于对账系统的演变主要需要从考虑数据的增长、任务资源的合理配置以及系统监控这几个方向去考虑。如果数据量持续增长到传统方式已无法处理,可以采用Spark Streming+Hive+Tidb等组合技术方案进行改进。//1.数据量百万级别一下使用传统方式即可2.百万以上引入中间件/大数据中间件
此外对账系统是一个以定时任务为主的系统,对于定时任务处理框架的选择可以采用分布式任务框架(推荐elasticjob/saturn)+自定义任务逻辑的方式综合处理(如有些任务存在先后顺序,如果框架本身不提供这类处理功能,则需要通过业务规则限制)。//分布式定时任务框架
而从系统监控角度,由于任务系统不同于实时交易流程,具有执行时间长、数据操作范围广泛的特点,除了进行正常的进程级别的监控外,对于各个任务的执行情况,也需要进行比较细致的监控,这部分可以通过监控打点等方式综合解决;而对于业务异常日志的监控则可以通过Sentry等日志监控工具进行监控。
分布式定时任务
作者:yangkai 网址:ykblog.top 来源:YK Blog 著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
分布式定时系统 一般对账系统都是N+1离线对账,所有上述所有模块的设计一般使用定时任务去执行。不可能所有模块、所有银行卡都用一个任务去执行,也不可能只用一台机器去执行,这样一天可能都跑不完所有的数据。 所以考虑到优化,一般设置为集群分布式的去跑任务,所以涉及一个分布式定时系统对对账系统来说很重要,考虑成本和时间问题,可以简单实现分布式任务效果。分布式定时系统的设计后续再单独探讨。 即使所有任务都按模块化去进行划分,按模块化单独起任务去执行业务逻辑,也会存在时间效率的瓶颈(因为下文提到的依赖关系,导致并不能让所有的任务都并行起来)。再加上银行卡号比较多的情况下,最好情况就是各个银行卡号并行处理,即并发粒度设计到银行卡号维度,使用多线程把所有银行卡的对账任务并行起来。
因为数据量大,百万以上,就要采用分布式集群服务-定时任务 处理数据。
100万~1000万/天,如何提高对账速度?
速度要求 要几分钟处理完毕。
二、缺陷:1、对账过程中查询相关数据,如果数据量巨大,对数据库性能影响较大,而且对账逻辑扩展极为麻烦;2、逐行比对算法效率较低,但算法上并无好的优化余地。如果采用数据库INTERSECT、MINUS对数据库压力也高;3、在业务量大的情况下(例如有上百家上游渠道需要对,每一家都有几十万条交易记录),对账服务器及数据库服务器负荷较高。即便采用读写分离,对账时候使用读库,压力一样很大;4、导入批量文件,逐行入库效率较为低下(每一次都需要建立网络连接、关闭连接)。
三、改进:1、涉及网络传输的,尽量采用批量方式操作,减少网络消耗及时间消耗;2、使用Redis等NOSQL数据库,降低数据库服务器的压力。同时在扩展上也容易,一台Redis服务器不够,可以无限制增加用于对账用的服务器;3、使用Redis的set集合的sdiff功能,利用Redis sdiff算法的高性能,比对上游记录和我方记录的差异。
作者:AskHarries 链接:juejin.cn/post/684490… 来源:掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
解决方案
1.直接在内存比较两个数据源的数据
2.引入第三方中间件
缓存或文件系统hdfs或大数据Hadoop
数据库表的设计
作者:yangkai 网址:ykblog.top 来源:YK Blog 著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
数据库模型
按以上设计模型,具体数据模型如下介绍
1.底稿数据表 //全字段记录-临时表
各个上游数据、下游数据抓取、解析的底稿数据 。 不只两张表,由具体业务决定;数据量比较大,一般按日期水平分表,按实际业务考虑要不要垂直分表。
2.清洗表 //比较字段
从各个上游数据、下游数据的底稿数据取部分字段。 不只两张表,由具体业务决定;数据量比较大,一般按日期分表。
3.对账结果表 //正常数据表和异常数据表
1)正常表 用来存放对上账的数据(即对账结果正常的数据,一般数据量比较大,需要按日期分表) 2)异常表 用来存放对不上账的数据(上游单边、下游单边、金额不等)。
4.对账汇总表 //所有已经对账的数据 即对对账数据的汇总
5.技术相关表 定时配置、账户配置、异常信息等等相关表
代码实现
1.参考文章里有的部分代码开源参考
2.开源软件-果龙支付,微信 支付宝对账源码
参考
这些文章都非常好,而且都是有实战经验的,都是支付公司的人写的文章 doc.cocolian.cn/essay/recon… //支付系统-对账
tech.meituan.com/2018/03/21/… //美团,非常好的文章,特别是画图。不过它的对账是内部不同系统的对账,即美团外卖平台订单和骑手直接的结算,而不是支付系统和银行直接的对账,不过思路是一致的。
juejin.cn/post/684490… juejin.cn/post/684490…
www.ityouknow.com/pay/2017/06… //纯洁的微晓,抄袭别人的
blog.itpub.net/31562044/vi… //内容都大同小异
zhuanlan.zhihu.com/p/41076594 //概念还解释的挺好的 //知乎推荐文章都挺准的,也可以看一下
如何比较数据? zhuanlan.zhihu.com/p/33594152 //两种方案