支付系统中热点账户的性能问题
热点账户类型 |
账户属性 |
实时需求 |
锁需求 |
处理方式 |
性能 |
业务大账户 |
内部账户 |
无实时余额查询 无实时提现 |
无需加锁 |
异步MQ延时处理 |
满足 |
大代理商账户 |
对外账户 |
无实时余额查询 无实时提现 |
没有加锁需求 |
异步MQ延时处理 |
满足 |
热门商户(推广) |
对外账户 商户账户 |
实时余额查询 实时提现 |
有加锁需求 |
串行化同步 |
亟待提升 |
一、按业务场景尽量拆分热点账户,分散压力
1)账户拆分,拆分主账户
此时解决方法就是再办一张同行的卡,或者其它银行的卡,一起承担存钱和提现的需求
2)新增多个子账户,
向银行申请,为该主卡办理多个子卡,用子卡进行分流
3)按功能进行划分
申请一个专门接收打款的卡
申请一个专门接受提现的卡
二、异步方式
4)异步队列延时处理
先把所有的打款、提现的请求入队列,延时处理账户余额更新
5)实在没招了,合并处理
把某个特征相似的操作进行合并处理。即把别人一万次打款请求合并为一个打款请求,此时最终只需要申请一次打款,其它人的卡逐个扣款
提现就不好解决了,可以增加一个提现缓冲卡,但是迫不得已,可以把多次提现请求,合并为一个请求,先从该账户把钱提到提现缓冲卡,再由提现缓冲卡分发给其它目标账户。
支付结算账户系统针对上述问题做了如下处理:
我们把热点账户按照金额变动方向分为加频账户(余额增加频繁)、减频账户(余额扣减频繁)、双频账户(余额增加扣减均频繁)。
加频账户处理
准实时更新余额。先将金额变动插入临时表中,由定时任务按照一定频率汇总发生额,并更新账户余额,而后删除临时记录。当加频账户减钱余额不足时,主动去汇总发生额。这里需要考虑主动汇总发生额和定时任务处理的并发情况,我们在该定时任务执行时设置redis锁,防止并发,主动汇总时会去判断这个redis锁是否存在,如存在证明定时任务正在执行,无需主动汇总,可能是真的余额不足。主动汇总同样会设置redis锁,定时任务同样会判断。
减频账户处理
将减频账户拆分多个子账户,减频子账户设置金额报警,如果某个减频子账户余额不足触发报警,会对该子账户做资金归集,将其他子账户余额归集到该子账户(每个子账户设置可归集金额限制)。如在交易过程中发现该子账户余额不足,转向使用其他子账户记账。由于拆分子账户,余额查询时需要汇总各个子账户余额返回;记录主账户流水需要记账后余额,这里需要异步计算汇总。当减频账户加钱时,需要平均分配入账到不通的子账户。
双频账户处理
将双频账户拆分多个子账户。加钱时,准实时更新余额,先将子账户金额变动插入临时表中,由定时任务按一定频率汇总发生额,将汇总的发生额更新进对应的子账户,并删除金额变动记录;减钱按照之前减频账户的逻辑执行。
支付宝需要有个账户记账,现在很多业务已经出现了很多热点账户。比如互联网大商家,\
账号有余额,主要用于不能扣成负数。 大并发交易下余额快速变化,导致数据库竞争等待。
原则: 不同的业务要求,不同的设计,同时会影响业务需求.
三大需求,是否都容易满足:
1.减款
2.加款
3.读取总金额
最简单设计: 帐户表+流水表. 每次帐户加减款都需要增加流水,和帐户变动.
业务需求: 高并发帐户.
技术选择 1. 悲观锁(高并发帐户), 乐观锁(普通并发帐户). 3. 顺序化 同步转异步,mq 降低峰值.
存储选择: redis 还是 数据库. redis本身并发能力就是比数据库要好. 但是单机支持的数据量不如数据库大. 只存放account的值的话到还好.
账户转账分两个接口,一个可扣成负数,一个不能扣成负数.
1 如何消除余额竞争呢?
方案一:变成两个账户 模仿 担保交易,设置两个账户 1. 扣款账户 2. 加款账户
1.1. 商家都是频繁加款 ,加款账户只记流水,不计算余额. 避免频繁竞争
1.2. 加款帐户的流水定时汇总到扣款帐户上.
1.3 扣款账户用于退款和提现, 因为频率不高. 即保证余额控制,也没有并发问题. 退款有些业务能扣成负数,有些业务不能.
缺点: 进入的钱不一定能时时能用. (对小商家不适用,比较计较)
优点: 这样就避免了热点账户的余额计算。
方案二: 账户分普通账户,加频账户,减频账户,双频账户
类型为加钱频繁账户,加钱不改变余额,定时任务收集改变。 捡钱操作时时进行。
减频账户,拆分子账户。
扣款只账户会有个问题,前面扣掉了,但是最后不够扣。
最佳方案,回滚,即逆操作,加款。
次佳方案, 使用只能扣成一次负数
双频账户:加款依然如此,减款同上。
延迟提现问题:即2天内收入只允许某种业务扣款(内部消费,代驾现金抵扣),但不允许提现扣款。
采用普通账户,但是要满足提现延迟方案?
小商家加的钱必须时时能用. 又要求延迟提现怎么办?
只能通过订单维度,目前这个订单现在有多少钱冻结中(已退款的钱不应该冻结). 展现哪些订单是冻结的,冻结金额是多少.
一旦钱被消费了, 账户余额可能少于订单的冻结的金额,可提现余额可能为负数.
客户可能来投诉, 因为他自己意识不到钱被消费了(抵扣信息费)和提现金额变少有关联.
原文链接:https://blog.csdn.net/xiaohanzuofengzhou/article/details/100938038