支付网关系统优化
POS前置系统
系统现状
|-------------|
| 负载均衡 |
|-------------|
|------|
| 应用 |
|------|
系统并发瓶颈
- ServerSocket单线程接收数据 -》 netty
- http调用第三方服务操作 -》改为异步http工具
- 日志同步IO操作 -》 改为log4j异步日志
- 轮询情况下sleep阻塞线程 -》改为协程,异步,或通知回调等方式轮询
- 数据库JDBC同步IO操作 -》暂不改动,考虑目前数据库响应速度较快
并发优化
高并发方案
Reactor异步方案
Vert.X + RxJava
spring-boot 2 reactive + ProjectReactive
协程方案
netty + quasar携程库
网关系统2.0方案
- 因决定要实现POS机的一机一密,系统会有大改动,趁此机会,可以重构网关系统的2.0版本
需求
- 高并发,高可靠性
- 保证之前版本的兼容性
- 最好http与tcp接口,保持相同的项目。
方案
方案一
- 一个tcp网关,解析8583报文,老版本直接透明转发(如果签名方式变化,可能需要重签名),新版本解析报文后并进行一些验证处理后,请求后端rest服务,轮询,关单等逻辑在网关实现。
- 一个http网关,进行验签,转发等操作。
- 后端采用微服务等模式,提供restful接口。
- 数据库维持不变
方案二
支付网关系统
数据库方面优化
交易系统
- 对于不经常变化并且可以接收一定时间的数据不一致状态的数据,如用户基本信息,用户支付信息,用户费率信息,支付产品配置,支付渠道配置等,使用缓存保存(redis),所有数据都从缓存中读取,减轻对数据库压力。
- 对于经常变化的数据,如订单信息,其特点为订单创建的很短一段时间内会被频繁的访问,可以在订单创建时分别缓存其商户号+商户订单号(key)-》主键ID(value),平台订单号(key)-》主键ID,银行订单号(key)-》主键ID(value),主键ID(key)-》订单数据(value),时间为3分钟(订单被创建支付成功并通知商户后,很少会被再访问)。不过要注意所有修改数据库订单时,需同步更新主键ID-》订单数据的缓存。
管理系统
- 管理系统一般会使用复杂的查询语句,并且查询的数据跨度很大,难以通过缓存进行优化,可通过数据库读写分离机制,将管理系统的读请求,分发到从库中,减少复杂查询对主库的压力。读写分离可通过数据库中间件(如mycat)或者mybatis插件来完成,他们对应用都是透明的。
IO优化
对服务请求的IO优化
- 目前向渠道请求,一般需要一秒以上才会收到响应,这段时间,线程一直在等待,造成极大的性能浪费。
对商户端的IO优化
账户表锁竞争优化
- 目前,每笔交易完成后,会同步向商户及代理商的账户中加账户余额,因此所有代理商下的订单都会需要获取代理商账户表的锁,当并发稍大(仅单代理商十几线程时),会出现长期获得不了锁,造成线程等待,无法返回商户数据的问题。
解决方案
- T1交易,商户对账户余额实时性要求不高,并且余额数据仅作为虚拟账户做参考,清算需对账完成后才会发起,可以对账户余额同步处理转异步处理,可以优化商户调用api的体验。当支付成功后,发送消息到mq,消费者获得消息,异步处理账户余额及分润信息。
- 异步处理,只能起到不影响交易,和削峰值的作用,当长期高并发时,消费者来不及处理mq消息,会造成消息堆积,甚至会使mq无法承受。
- 资源竞争问题,1是增加资源,2是减少竞争者,因为账户为一条记录,难以增加资源,但是可以通过合并账户操作,来减少竞争。例如,可以每一百条账户操作记录,起一个事务,将需要变化的总金额通过应用计算后,一次增加账户余额中,可以极大的减杀竞争,或者使用定时器,没隔一段时间,将成功的交易余额一次加到账户余额中。