分享 解决问题的套路:数据库高写入挑战

early · 2021年12月26日 · 最后由 early 回复于 2021年12月27日 · 647 次阅读

在平时解决问题时,往往开始会一头雾水,在跌跌撞撞试错很多后,才勉强得到了合格的答案。但反观有些人非常有章法且迅速地就拿出了解决方案,有板有眼,既有说服力又预留了不少可能性。高下立判。

其实对于大部分常规问题,都是有套路可循的,别人动作快质量高,其实是基于套路的迅速复制,而且在大量复制的过程中,沉淀出了场景应变能力,将各类知识串起来,形成了高维度的能力代差。

本文开启一个系列,基于历史上对问题解决过程的复盘,我简单总结了一个套路。本文及后续的系列,会通过实际案例来对套路进行阐述及迭代。

不仅限于问题解决方案的探讨,将注意力往下沉,关注解决方案如何诞生。通过对元能力的持续总结,提升沉淀效果。

套路分为几步:

  1. 第一性原理:通过连续追问直到问题根源,形成一颗树
  2. 演绎回溯:从树的底部,往上逐层脑爆解决方案
  3. 归纳:将脑爆方案分类梳理组合,得出优缺点
  4. 带入变量:带入系统变量,通过优缺点变化趋势,找出最佳匹配
  5. 更进一步:场景扩展延伸,形成应对预案,夯实系统扩展性

场景

榜单是直播非常重要的场景,这里承载了用户的存在感,主播荣誉感,直接影响商业变现。

榜单的本质是,某种积分规则在一定时间区间的排序结果,例如用户打赏排名,对花钱金额做排序;如主播营收榜,对主播挣的钱做排序。这种排序一般有一个时间区间限制,例如日榜、周榜。

每一次积分变化,都会对积分值做更新,产生新的排序结果。

冲突

一般为了持久化和可靠性,都会用数据库做存储。在积分变化时,对应的就是数据库的一次 update 操作:score = score + 增量,对一致性要求高的场景,还需要在事务中操作并写一次流水。

当某个大主播房间出现大规模送礼时,问题来了:

  1. 热点问题: 主播榜所有用户送礼对应的积分会写同一行数据
  2. 写放大:当同时有很多个榜时,一次送礼会在榜单出现多次写

一般的系统设计,在送礼高峰下数据库很可能会被打瘫痪。如果强行做缓冲,那更新会延迟,损害用户体验。

怎么办?我们来套一下上面的框架。

解决方案

第一性原理

通过连续追问形成一颗问题树,直到无法拆解或无法解决。

演绎回溯

从问题树根部往上逐层提出解决方案,不设定约束进行头脑风暴:

归纳

基于头脑风暴的内容,整合出关键的解决方案。

方案之间往往需要组合,甚至是通过开关控制每个 feature 是否启用。

带入变量

方案清单出来了,但是该选哪一个? 怎么组合? 不通的场景需求,答案往往有差异,此时需要带入具体的业务场景变量,看优缺点如何变化,选择可以接受的那个。

如果主播寡头化明显,写打散的方案明显不行; 如果实时性、可靠性进一步要求提升,写合并方案必须要能应对,否则不能用。 如果用户进一步增长,分库分表肯定要搞。 如果业务逻辑复杂化,则批量写入的方案不可取。

根据实际变量选择最合适的就行,随着环境改变、基建升级,可以重新跑一次套路。总体来说,一般的场景,需要分库分表 + 写聚合配合进行,这两者本身可以做到彼此解耦合。

更进一步

在上面的变量带入中,有两个陷阱:

  1. 有些变量拿不准
  2. 环境往往有限制,例如资源有限

此时要在可扩展性上做余留。以下是举例。

总结

以上是基于榜单这个业务,对套路做的一次简单演练,要真实体验套路的威力,还是得挑一个问题动手试试。

高速成长 = 套路 * 重复次数。

另外,套路本质是思路和决策的加速器,一切的根基来源于朴素知识的格物致知。

所以基础知识的充实非常重要,这不是简单学习几个套路和方法论就可得到的。

感觉楼主是在一个 TP 库上造一个 AP 的轮子。

榜单明显是一个 OLAP 场景,第一要选合适的工具,看楼主的描述都是在 OLTP 库上来解决这个问题,所以才要自己解决写入问题。

如果你的架构上允许,同步一份 TP 库到 AP 库。榜单其实就是一个读的问题,和写完全没有关系,所以上面的问题都不存在。

所以问题就变成了:

  • 实时榜单,那么选择流处理工具:flink、ksqlDB、materialize 之类
  • 非实时榜单,那么选 clickhouse、tiflash、bigquery 之类,加缓存或者异步刷新
hooopo 回复

你这个分析很到位,只是理想骨感,好多时候业务方案受限于基建生态和打通成本。当规模和成本进一步增大到难以承受时,最终会倒逼走向你的方案。

之前有次 ES 负载不均,搜索服务一直报错,用户开始反馈,更尴尬的是没熔断。搜索团队给了各种建议。我们的负责人(业务网关在我们这)说,把这个功能去掉,上线。。。去掉了一个月,也没有用户发现。

我的第一反应是业务规划, 找出最核心的业务, 依次保证

比如我拍个个脑袋: 先保证礼物能送出,再保证礼物消息能推送到主播和金主,再保证其他用户能看到, 再保证小时榜级别的更新, 再保证其他的。

之后再拆到 礼物送出是需要保证 ACID 的, 其他的 异步慢慢来, 礼物推送到主播, 最小消费一次推送, 其他用户消息推出去就行。 再就是榜单计算, 比如 压力大的情况下, 小时榜转化为 5 -10 秒一次结算,其他榜结算方式改为 5 分钟甚至 1 小时一结算降低压力。能放内存放内存,能不扔库不扔库。 缓存 能分区域就分区域, redis 按地理区域划分, 之后读的时候累加即可, 不用做到原子性

当然这些都是基于我对直播粗浅的理解, 在考虑技术实现成本的情况下想的一些皮毛,为大佬抛砖引玉。 若有问题, 还请别见笑

jicheng1014 回复

说的好,我补充点。你这个是技术降级时的思路,没办法了才列优先级。业务视角上所有都是重要的,缺一不可。正常情况下,技术也是可以都做好的。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号