高并发热点账户分析

 

[吃瓜R]之前面试ZJ问了一个热点账户问题,答得不好,今天就来好好分析下热点账户到底该怎么设计

 

[得意R]什么是热点账户

同一个账户,短时间内,大量的入账和出账

 

[吃瓜R]账户写入基本流程

事务内完成账户余额的变更与操作明细的记录,期间至多有一个线程抢占资源,其余线程block或直接返回失败

 

[吃瓜R]解决热点账户的思路及优缺点

1.限流。

-- 既然顶不住那么高的流量,那就限制写入的流量吧。

-- 优点:账户的写入是可控且正常的。

-- 缺点:高并发时,由于限流会导致转账失败率极大提升,对用户极不友好

2.先插入,后统一汇总写入

-- 数据库的insert几乎无资源竞争,先写入到一张流水表中,后比如10s,统一汇总到账户中

-- 优点:对于频繁入账的性能提升显著

-- 缺点:出账场景如果不判断当前余额,可能会出现账户透支的可能性。

3.缓冲写入

-- 某一时间段突然的大量写入,那就先写入mq中,以数据库事务可承受的速率消费消息写入账户

-- 优点:削峰填谷,控制了高并发抢占资源的问题

-- 缺点:1.mq消费消息失败,结果需要另行通知用户 2.如果账户一直是热点账户,就不存在谷这么一说,mq的削峰填谷也就无异议了

4.拆分成多个子账户

-- 单个账户只有一个资源,那就拆分成多个子账户,抢占被分摊的资源变多了

-- 优点:hash进行账户的负载均衡,解决了部分抢占同一个资源的冲突的问题

-- 缺点:子账户余额较分散,单一子账户余额不足,但是整体账户其实是充足的,因此可能会影响转账成功率,且多个子账户的操作,处理起来较麻烦

5.使用内存数据库

-- 问题的原因是磁盘写入慢,那我就直接内存写入

-- 优点:写入速度大幅增长

-- 缺点:断电即失,没有数据库事务保证,得详细考虑边界场景,因为资金安全是及其重要的。

6.提升单台机器的性能,升级CPU

-- 只是一个权宜之计,解决不了根本的问题

 

[微笑R]简单设计一下

背景:3笔加100元,1比减200元的同时来了。

设计额外数据结构:

1.操作流水表(记录每笔交易记录)

2.redis缓存(记录每个账户的余额)

  1. 入账则只记流水表

  2. 出账从redis缓存中判断当前余额(直接参与计算>0则足够,<0则不足(不足的话先记录到重试队列,等至少汇总一次后重试判断如果还不足则返回不足))

+100的写入流水表中,-200时此时缓存余额不足,记录到重试队列中,并且缓存余额需要加回来200(如果加回来失败呢?后续有什么手段确保成功)

10s后进行汇总,锁定账户资源,入账流水等账户写入成功后,加入缓存中

 

讨论如下方案的区别?各有什么好处吗?

  1. 入账不直接写缓存,而是等10s后汇总时再写入

  2. 入账直接写缓存

 

入账直接写入缓存

  1. 实际账户并没入账

  2. redis缓存余额脏数据很难替换(也是筛选入账)

 

 

边界点:

  1. redis写失败了,缓存中的脏数据有什么机制替换

    1. 以入账在汇总时再写入缓存为例

    2. 每过5min/有redis写入失败时?,就重新替换一波。

      如何替换?

      -- 生成一个新的redis的key,如果新key存在,则后续的出账操作全部返回失败,并落入重试队列中,原key的计算=汇总后数据库余额即可

  2. redis挂了,这套流程还能否正常运转

    1. mq策略(先接收数据库慢慢处理,出账也是按照顺序逐条,异常则落重试队列)

    2. 兜底限流,在数据库可承受范围内事务转账

 

posted @ 2022-12-28 19:28  程序杰杰  阅读(368)  评论(0编辑  收藏  举报