zoukankan      html  css  js  c++  java
  • 支付对账系统序章:千万级数据对账怎么这么难?

    支付对账

    很早 之前写过一篇支付对账相关文章,那时候负责对账系统日均处理数量比较小。

    那最近正在接手现在的对账系统,由于当前系统日均数量都在千万级,所以对账系统架构与之前架构完全不一样。

    那就这个话题,聊聊如何实现千万级数据支付的对账系统。

    什么是对账?

    我们先来回顾下什么是对账?

    也许你对对账这个概念比较模糊,但是这个场景你肯定碰到过。

    上班路上买了一个煎饼,加了根里脊与王中王,然后你扫了老板的二维码付了 10 元钱。

    你跟老板说你已经付了 10 元钱,老板看了下手机,果然有一条 10 元支付记录,老板确认收到钱,然后就把煎饼给你。

    这个过程,你说你付了 10 元,老板确认收到 10 元,这就是一只简单的对账过程。

    回到我们支付场景,用户下单使用微信支付 100 元购买了一个狗头抱枕,这时我们这边会生成一条支付记录,同时微信支付也会生成记录。

    那微信第二天就会生成一个账单记录,我们拿到之后把我们的交易记录跟微信记录逐笔核对,这就是支付对账。

    为什么需要对账?

    正常支付的情况下,两边(我们/第三方支付渠道)都会产生交易数据,那支付对账过程,两边数据一致,大家各自安好,不用处理什么。

    但是有些异常情况下,可能由于网络问题,导致两边数据存在不一致的情况,支付对账就可以主动发现这些交易。

    对账可以说支付系统最后一道安全防线,通过对账我们可及时的对之前支付进行纠错,避免订单差错越积越多,最后财务盘点变成一笔糊涂账。

    支付对账系统

    开篇先来一张图,先来看下整体对账系统架构图:

    整个对账系统分为两个模块

    • 对账模块
    • 差错模块

    对账模块,主要负责对账文件拉取,数据解析,数据核对,数据汇总等任务。

    差错模块是对账模块后置任务,对账模块核对过程产生无法核对成功的数据,这类数据件将会推送给差错系统。

    差错系统将会根据规则生成差错订单,运营人员可以在后台处理这列数据。

    今天这篇文章先不聊具体的系统设计,先来回顾下之前的对账系统设计,简单了解下对账的整体流程。

    对账系统设计

    对账系统如果从流程上来讲,其实非常简单,引用一下之前文章流程图:

    https://studyidea.cn/articles/2019/08/26/1566790305561.html

    整体流程可以简单分为三个模块:

    • 本端数据处理
    • 对端数据处理
    • 本端数据与渠道端数据核对

    本端数据指的是我们应用产生的支付记录,这里根据账期(交易日期)与渠道编号获取单一渠道的所有支付记录。

    对端数据指的是第三方支付渠道支付记录,一般通过下载对账文件获取。

    由于每个渠道下载方式,文件格式都不太一样,对端数据处理的时候需要将其转化统一数据格式,标准化在入库存储。

    网上找了一份通用账单,可以参考:

    对端数据转化存储之后,对账流程中,对端数据也需要跟本端数据一样,获取当前账期下所有记录。

    两端数据都获取成功之后,接下来就是本地数据逐笔核对。

    核对流程可以参考之前写的流程:

    上面流程其实也比较简单,翻译一下:

    查找本端数据/对端数据,然后转化存储到 Map 中,其中 key 为订单号,value 为本端/对端订单对象。

    然后遍历本端数据 Map 对象,依次去对端数据 Map查找。如果能查找到,说明对端数据也有这笔。这笔核对成功,对端数据集中移除这笔。

    如果查找不到,说明这笔数据为差异数据,它在本端存在,对端不存在 ,将其移动到差异数据集中。

    最后,本端数据遍历结束,如果对端数据集还存在数据,那就证明这些数据也是差异数据,他们在对端存在,本端不存在 ,将其也移动到差异数据集中。

    PS:上述流程存在瑕疵,只能核对出两边订单互有缺失的流程 ,但是实际情况下还会碰到两边订单都存在,但是订单金额却不一样的差异数据。这种情况有可能发现在系统 Bug,比如渠道端上送金额单位为元,但是实际上送金额单位为分,这就导致对账两端金额不一致。

    之前对账系统日均处理的支付数据峰值在几十万,所以上面的流程没什么问题,还可以抗住,正常处理。

    但是目前的支付数据日均在千万级,如果还是用这种方式对账,当前系统可能会直接崩了。。。

    千万数据级带来的挑战

    第一个,查询效率。

    本端/对端数据通过分页查询业务数据表获取当天所有的数据。随着每天支付数据累计,业务表中数据将会越来越多,这就会导致数据查询变慢。

    实际过程我们发现,单个渠道数据量很大的情况下,对账完成需要一两个小时。

    虽然说对账是一个离线流程,允许对账完成时间可以久一点。但是对账流程是后续其他任务的前置流程,整个对账流程还是需要在中午之前完成,这样运营同学就可以在下午处理。

    第二个问题,OOM。

    上面流程中,我们把把全部数据加载到内存中,小数据量下没什么问题。

    但是在千万级数据情况下,数据都加载到内存中,并且还是加载了两份数据(本端、对端),这就很容易吃完整个应用内存,从而导致 Full GC,甚至还有可能导致应用 OOM。

    而且这还会导致级联反应,一个任务引发 Full GC,导致其他渠道对账收到影响。

    第三个问题,性能问题。

    原先系统设计上,单一渠道对账处理流程只能在单个机器上处理,无法并行处理。

    这就导致系统设计伸缩性很差,服务器资源也被大量的浪费。

    千万数据级对账解决办法

    上面系统代码,实际上还是存在优化空间,可以利用单机多线程并行处理,但是大数据下其实带来效果不是很好。

    那主要原因是因为发生在系统架构上,当前系统使用底层使用 MySQL 处理的。

    传统的 MySQL 是 OLTP (on-line transaction processing),这个结构决定它适合用于高并发,小事务 业务数据处理。

    但是对账业务特性动辄就是百万级,千万级数据,数据量处理非常大。但是对账数据处理大多是一次性,不会频繁更新。

    上面业务特性决定了,MySQL 这种 OLTP 系统不太适合大数据级对账业务。

    那专业的事应该交给专业的人去做,对账业务也一样,这种大数据级业务比较适合由 Hive、Spark SQL 等 OLAP去做。

    总结

    今天本篇文章只是一个序曲,主要聊聊对账业务基本流程,聊聊之前系统架构在大数据下存在的问题。

    后面文章再会介绍下大数据下对账系统如何设计,对账之后差错数据如何处理,尽请期待。

  • 相关阅读:
    代码块&继承&final关键字
    Java基础
    我的学习笔记
    CF743C 题解
    洛谷P4180 题解
    洛谷P3402 题解
    洛谷P3919 题解
    Noi.ac#30 题解
    Noi.ac #65题解
    Noi.ac #51题解
  • 原文地址:https://www.cnblogs.com/mengcheng9300/p/15723134.html
Copyright © 2011-2022 走看看