应对单条高频的数据修改方案


写在前面
在高并发场景下,某些业务场景可能存在对于单条数据高频修改的需求。举个简单的场景:在MQ消费时,对账户进行加减操作,保证账户(较少账户)的总金额和流水的总金额相等。中间可能存在对于账户进行频繁update的操作,如果直接用DB接高频修改,瓶颈会出现在行级锁占用较长时间,导致消费能力不足,导致MQ消息积压严重。
对于我们来说,要求应对100qps。
问题拆解
作为有经验的RD,需要避免一上来就进入方案设计和编码阶段的毛病,首先以产品需求角度分析整个需求场景的合理性。
100qps高频修改,是什么场景呢?上文知道了是账户加减操作。
解决方案
很多人想到的第一个解决方案就是批量处理。这种方案也是高并发高性能系统中常用到的解决方案,面向高并发大数据量场景的kafka在高性能设计上的一个重要方式就是批量处理写请求,所以我们首先可以考虑借助于快照形式,搞成批量修改,避免一次次修改造成的资源浪费和压力,这样可以将100qps降低到50qps或者20qps。
接下来就是考虑通过何种方案实现批量修改了。
首先考虑引入缓存方式。批量修改操作收敛到缓存中,但是缓存的往往面对的问题是数据可能丢失,当然可以依赖于具体缓存介质的特性实现数据不丢失。
另一个想到的解决方案还是拆分,拆分是高并发场景下经典的解决方案。我们可以考虑将目标账户进行拆解,拆分成多个子账户做操作,这样可以将热点操作分散。
还可以考虑CQRS方案,将操作以流水方式进行记录,拆分组合一次次流水,可以保证数据不丢失,更新缓存,合并多次操作日志。
交易系统高频修改场景
将方案扩展下需求场景,我们之前做交易系统,需要做到高频且数据一致性要求。类似的高频操作场景一般依赖于3张表:账户表,流水表,日志表。整体方案上需要满足事务,且对账户操作修改增加悲观锁。
整体方案难度在于记录流水和合并日志消息。
整体方案依赖于账户水平拆分,解决读写瓶颈,缓存持久兜底保护DB,引入异步化处理流水,更新缓存,合并多次操作日志。
在整合了MQ异步,DB更新,缓存兜底,还需要做好应用层排队,和引擎层排队。
批量操作,流水表加批次号,按照批次号进行批次合并,异步更新账户信息。
如果对于金融场景来说,对于持久化存储和数据一致性还是有要求的,缓存可能丢数据,账户金额这种可能无法接受。
所以一般是持久化队列,消费异步消费,消费时批量更新,减少频繁更新锁占用。
在进行账户拆分之后,对于MQ使用来说可以按照账户建立partition,不异步消费不需要担心一个账户的并发更新。场景上避免不了并发处理,并发就拆分partition吧,当然拆的不够细热点问题可能就严重了。
最后
今天我又YY了一个高并发场景需求,最近准备就高频交易系统场景下方案做一些梳理,因为某些方案和背景可能涉及到公司核心系统,所以采用这种YY需求的方式进行讨论。未来考虑做一套课程将高频交易系统的架构和难题进行拆解和总结,准备叫《那些年我们拆解的高频交易系统解决方案》吧。