1
qxdo1234 OP 有类似的解法的,也可以一起回复,大家一起开放讨论,不限制具体使用的存储和计算的方式,但是想了解一下,有没有比较完善的解决方案。
|
2
wenxueywx 212 天前 1
一、同时跟你发生交易的客户数量是有限的;
二、采用 mysql 事务实现,受限于行锁,高并发下会有严重的锁等待现象,分桶可以缓解,例如你可以把公司账号分为 0-9 共计 10 个子账号。查找账号时引入随机性没有用,因为你总的并发不会因为你的随机性降低。 三、 高并发下,随着并发数( n )的增加,innodb 的死锁检测占用的资源会以 n^2 级数上升,你可以简单暴力地关闭死锁检测,但是这治标不治本;治本的方法是在 innodb 中明确地需要串行执行地操作不要进入引擎层,可以在业务上进行排队,排队时还可以对队列进行优化,比如同时 100 人并发转入到子账号 0 ,此时数据库中给子账号 0 增加余额,以及记录流水的操作是明确需要串行执行的,如果进行业务上进行排队优化,你可以合并这些转入操作到一次数据库变更中。 |
4
KIDJourney 212 天前 1
啥业务要求即时到账啊,在线转离线呗
搞个队列或者搞个 mysql 任务表慢慢离线扫去 |
5
qxdo1234 OP @KIDJourney 假定的是一个对并发,以及到账处理时效要求比较高的场景,毕竟你也不想你的客户做完操作以后 还要等大概 1-2min 之后才能离线看到自己的账户变动嘛,你可以理解成,比如我们运营一个超高价值波动的产品,晚 1-2min 的话 就一个天上一个地下了。肯定在有解决方案的情况下,要求更快的处理时效,如果真的是没有解决方案的话,才可以接受大概延迟几秒的处理时效。慢慢扫 可以解决问题,但是不是太符合本场景,不过还是谢谢。
|
6
waitingChou 212 天前 1
分桶是一个简单的抗高并发的思路,还要继续优化出一个复杂思路的话,感觉 innodb 处理写入操作的思路也可以参考一下。
简单来说就是把数据加载到内存, 有请求先改内存数据, 再写入到 "redolog"。 后台任务有空再把 redolog 落盘,落盘的时候没有并发,可以做得比较快。 把高并发的冲突操作改成了纯内存 + 无锁顺序写 |
7
justRua 212 天前 1
是不是可以把加钱、扣钱两个动作区分对待,扣钱失败的场景一般是用户余额不足之类的业务异常需要立马回滚事务,但是加钱失败则可能是出现锁竞争、网络之类的系统异常导致,重试就好了不需要回滚整个事务,可以适当延迟。
用户余额加钱逻辑: 1.写入账户流水; 2.发送 MQ ,流水表加一个同步状态字段。 后面异步执行: 3.用消费者根据 MQ 消息去扫描流水表、批量的把多个加钱的记录金额合并为一个 update 操作用户余额,把同步状态更新为已同步。 查看用户余额逻辑: 查询用户余额表 + 流水表未同步的记录金额 扣钱逻辑不变,但可能出现扣钱时,余额还没加上流水表未同步的加钱金额,导致余额不足扣钱失败,应该也还好。 |
8
dode 211 天前
引入 Redis 记录公司账号变化状态
|
9
haxixi 210 天前
公司账户的变化用 redis 记录
账户流水用 mq ,然后写流水表 如果 redis 出现宕机消息丢失,用流水表恢复 redis 丢失的消息 |