美文网首页
浅析聚合支付账户体系的高并发与热点数据问题

浅析聚合支付账户体系的高并发与热点数据问题

作者: 文艺小程序员 | 来源:发表于2019-09-29 14:42 被阅读0次

在聚合支付开发的初期,大家一般都是加班加点尽可能多的实现现阶段各种丰富的支付方式,如H5支付、APP支付、小程序支付等,但随着支付能力的提升,大家会发现其实聚合支付系统周边的一些配套系统也尤其的重要,如支付账户系统、支付日志归系统、支付业务数据统计系统等等,这些周边的系统对支付核心系统出现问题后的定位与分析会有很大的帮助。

聚合支付在一定程度上与支付机构有一定的相似度,大家为了更好的了解每个接入聚合支付的商户的资金情况,在一定程度上都会引入账户体系,但是随之也会出现一个问题,就是账户的高并发与热点数据问题,以我在工作中所遇到的问题为例和大家分享,同样也欢迎答应大家一起进行讨论。

一、产生问题:账户数据高并发与热点数据

在聚合支付中我们会给每一个商家创建一个账户,当商家有支付与退款的行为时,都会动态的更新余额,随之会产生一条流水数据,为了保证资金的准确性我们使用了悲观锁,将查询余额、更新余额、插入流水作封装一个事务,我知道数据库的更新操作一个时刻只能有一个会话进行操作,所以在大量的并发操作下操作余额数据会出现数据库行锁的等待情况,严重的影响了系统的效率与吞吐量。

这时候大家可能会想到一种方案,就是采用异步的方式,在不影响主流程的情况下,用异步的方式来进行记账,让数据库慢慢的处理,这也是解决该问题的一个思路,但是不能从根本上解决该问题。

二、尝试解决:优化业务流程、事务处理与SQL

A:问题分析
遇到这个问题我首先归纳了能够更新该条余额记录的操作,对于聚合系统来说主要应该有三类。

  • 支付流程:当用户支付成功时,在该商户的余额上加相应的金额;
  • 预退款流程:用户退款时,如果该商户的账面金额大于退款金额,则将退款金额先冻结,然后进行退款,如金额不足则不允许退款;
  • 退款流程:如用户退款成功,则将冻结金额解冻,并对余额进行扣减。

B:优化流程
针对以上的三种流程,我们提出的方案如下:

  • 针对支付流程与退款流程:先在应用中进行缓存,如3秒内缓存累计需要增加或者扣减的余额,从而降低数据库的更新操作的频率,缓解数据库行锁的争抢等待。
  • 针对预退款流程:将原有的事务(下图现状部分)改造为非事务(下图优化部分),并优化SQL,利用数据库自身去竞争锁资源,大体优化流程见下图。


    预退款流程优化

C.效果分析
针对这套优化方案我们经过测试后发现性能有一定的提升,但该方案还存在以下几个问题。

  • 支付流程与退款流程的优化:由于缓存累加的操作在应用上处理,如果单个应用节点的应用出现了问题会损失这部分数据,如果要是引入redis进行缓存,又要依赖一个组件。
  • 预退款流程优化:在事务上可以说将“悲观锁”改为“乐观锁”,但是通过测试发现效率没有“质变”的提升(毕竟update语句始终需要行锁),而且优化后更新与插入操作不在一个事务中,最终可能会导致资金的差异,影响数据的最终一致性。
三、推荐方案:利用分治的思想解决该问题

虽然第二部分的优化方案在一定程度上缓解了高并发与热点数据的问题,但是总感觉还不是一个最优的方案,因为为了解决这个问题,引入了其他的问题,以及要考虑到应用的高可用性。

话外音:有一天晚上打完球回来,我就在想支付机构是如何做到这种资金的强一致性,正恰好一个小伙伴也在加班,所以和小伙伴简单的讨论了一下,的确也开阔了自己的思路,最后通过查阅资料,发现大部分都采用了“分治”的思想来解决账户数据的高并发与热点数据问题。

A:数据缓冲(加频账户)
与之前的思路大体一致,先缓冲数据然后再进行更新,减少数据库行锁的争抢与等待时间,在有余额变动时,将所有加频数据(增加金额)缓冲在数据库的一张临时表中。那就需要一个定时任务在单位时间内对临时表的数据进行汇总,然后将汇总的金额一次性更新到余额表中。当然这其中也会出现一个问题,就是如果商户的余额不足且临时表中还有加频数据缓冲时,那就需要主动对临时表数据进行汇总并一次性同步到余额表中。这样就会出现两个线程同时发生汇总数据并更新余额的情况,这就需要使用锁来进行控制(可以使用Redis来设置锁)。

加频账户优化方案

B:账户拆分(减频账户)
将账户进行拆分,一条账户拆分为N个子账户,这样再减频(扣减金额)数据时,可以减少对原本一条记录的锁进行争抢与等待,同时需要设置一个余额告警,当有子账户的资金不够时,可以将其他子账户的金额归集一部分到该子账户中或将该笔交易转移至其他账户余额充足的子账户进行操作,当然这其中也有一个问题,就是查询该账户总金额时,需要对所有子账户的金额进行汇总操作。

C:双频账户
在大多数情况账户不单单的只增加金额或者扣减金额,一般情况下都是两者相结合,就跟大家的银行卡账户余额一样,你在消费的同时,可能有会给你转账。这样大家就可以将A、B两种思路相结合,将账户进行拆分,临时表在汇总金额时,可以一次性将增加的金额按照比例分到不同的子账户中。

D:数据的一致性
这种加频和减频账户数据的方法虽然很有效,但是由于一些客观的原因,可能会导致余额的不准确性,那我们可以再准备一张记账流水表,定期的对数据进行稽核,来保证账户数据的最终的一致性。

小结

面对这种高并发与热点问题,总结起来就是利用“分治”的思想,一条记录经常出现锁争抢与锁等待,那就想办法降低争抢锁和所等待的情况,我们可以较少对该热点数据进行更新或将大热点数据分为小热点数据。

PS:祝大家十月一假期愉快☺

相关文章:https://yq.aliyun.com/articles/718383

相关文章

网友评论

      本文标题:浅析聚合支付账户体系的高并发与热点数据问题

      本文链接:https://www.haomeiwen.com/subject/zhqcuctx.html