zoukankan      html  css  js  c++  java
  • 支付系统对账算法优化方案 转

    支付系统对账算法优化方案  转 http://www.yeeach.com/post/1318#comment-152796

    一、目前对账的算法:

    1、从上游渠道(银行、银联等金融机构)获取对账文件,程序逐行解析入库

    2、在存储过程中,以上游对账文件的表为基准,程序逐行读取并与我们系统的交易记录/账务记录(有账务系统情况下,合理方案应该是于账务记录)对比,查找出差异记录。

    3、以我们系统的交易记录/账务记录为基准,程序逐行读取与上游对账文件对比,查找出差异记录

    二、目前对账算法问题:

    1、使用存储过程,对账过程都在数据库端完成,对数据库性能影响较大,而且对账逻辑扩展极为麻烦

    2、逐行比对算法效率较低,但算法上并无好的优化余地。如果采用数据库INTERSECT、MINUS对数据库压力也高。

    3、在业务量大的情况下(例如有上百家上游渠道需要对,每一家都有几十万条交易记录),对账服务器及数据库服务器负荷较高。即便采用读写分离,对账时候使用读库,压力一样很大。

    4、导入批量文件,逐行入库效率较为低下(每一次都需要建立网络连接、关闭连接)

    三、对账算法优化思路:

    1、涉及网络传输的,尽量采用批量方式操作,减少网络消耗及时间消耗

    2、使用Redis等NOSQL数据库,降低数据库服务器的压力。同时在扩展上也容易,一台Redis服务器不够,可以无限制增加用于对账用的服务器。

    3、使用Redis的set集合的sdiff功能,利用Redis sdiff算法的高性能,比对上游记录和我方记录的差异

    四、对账算法说明:

    1、利用Oracle/Mysql的load data infile将对账文件批量导入到数据库

    2、程序读取上游账务记录表,对上游账户记录执行select  concat(channel_id, ":" , order_id , ":" , HASH_MD5(channel_id , order_id , amount , status , timestamp1 , timestamp2 ,…) )  as hashid from table ,得到对应的SET集合。

    这里思路是将需要对账的记录拼成格式为:channel_id:order_id:hashid形式的串,以便作为Redis SET集合的item。

    其中channel_id和order_id用于标识对应的渠道及订单,只是例子,根据实际需要补充。之所以要在hashid前面带上channel_id和order_id,主要目的是在sdiff后,能够作为主键,根据set结合的item查找出对应的数据库记录。

    3、对我方的交易记录表/账户历史表采用上一步的类似算法,得到对应的SET结合

    4、采用Redis的pipeline功能(Redis的各种客户端,包括java客户端jedis 都提供此功能),将上游账务记录SET集合和我方的交易记录/账务历史记录SET集分别批量执行sadd插入Redis,得到两个SET集合。

    由于单条记录sadd 插入Redis效率较差(每一次都涉及网络open、close、传输消耗),因此使用Redis的pipeline功能,已实现批量入库功能。

    可以参考:http://redis.io/topics/mass-insert

    5、利用redis的sdiff功能查找出上游账务集合与我方记录集合的差值

    6、从sdiff 集合中channel_id:order_id:hash,定位对应的数据库记录,更新对账状态。

    具体性能及实现可以在实现后测试对比一下,应该会有大幅的性能提升。

  • 相关阅读:
    数据库表结构变动发邮件脚本
    .net程序打包部署
    无法登陆GitHub解决方法
    netbeans 打包生成 jar
    第一次值班
    RHEL6 纯命令行文本界面下安装桌面
    C语言中格式化输出,四舍五入类型问题
    I'm up to my ears
    How to boot ubuntu in text mode instead of graphical(X) mode
    the IP routing table under linux@school
  • 原文地址:https://www.cnblogs.com/gym333/p/6252000.html
Copyright © 2011-2022 走看看