数据库缓存没预热会怎样?我帮大家逝了下……

五阳 2024-05-28 10:46:00
缓存不预热会怎么样?我帮大家淌了路。缓存不预热会导致系统接口性能下降,数据库压力增加,更重要的是导致我写了两天的复盘文档,在复盘会上被骂得狗血淋头。

 

悲惨的上线时刻

 

事情发生在几年前,我刚毕业时,第一次使用缓存内心很激动。需求场景是虚拟商品页面需要向用户透出库存状态,提单时也需要校验库存状态是否可售卖。但是由于库存状态的计算包含较复杂的业务逻辑,耗时比较高,在500ms以上。如果要在商品页面透出库存状态那么商品页面耗时增加500ms,这几乎是无法忍受的事情。

 

如何实现呢?最合适的方案当然是缓存了。我当时设计的方案是如果缓存有库存状态直接读缓存,如果缓存查不到,则计算库存状态,然后加载进缓存,同时设定过期时间。何时写库存呢?答案是过期后,cache miss时重新加载进缓存。由于计算逻辑较复杂,库存扣减等用户写操作没有同步更新缓存,但是产品认可库存状态可以有几分钟的状态不一致。为什么呢?

 

因为仓库有冗余库存,就算库存状态不一致导致超卖,也能容忍。同时库存不足以后,需要运营补充库存,而补充库存的时间是肯定比较长的。虽然补充库存完成几分钟后,才变为可售卖的,产品也能接受。梳理完缓存的读写方案,我就沉浸于学习Redis的过程。

 

第一次使用缓存,我把时间和精力都放在Redis存储结构,Redis命令,Redis为什么那么快等方面的关注。如饥似渴地学习Redis知识。

 

直到上线阶段我也没有意识到系统设计的缺陷。

 

代码写得很快,测试验证也没有问题。然而上线过程中,就开始噼里啪啦地报警,开始我并没有想到报警这事和我有关。直到有人问我,“XXX,你是不是在上线库存状态的需求?”

 

我人麻了,”怎么了,啥事”,我颤抖地问。

 

“商品页面耗时暴涨,赶紧回滚。”一个声音传来。

 

“我草”,那一瞬间,我的血压上涌,手心发痒,心跳加速,头皮发麻,颤抖的手不知道怎么在发布系统点回滚,“我没回滚过啊,咋回滚啊?”

 

“有降级开关吗?”一个声音传来。

 

"没写……"我回答的时候觉得自己真是二笔,为啥没加降级啊。(这也是复盘被骂的重要原因)

 

那么如何对缓存进行预热呢?

 

如何预热缓存

 

 
灰度放量

 

灰度放量实际上并不是缓存预热的办法,但是确实能避免缓存雪崩的问题。例如这个需求场景中,如果我没有放开全量数据,而是选择放量1%的流量。这样系统的性能不会有较大的下降,并且逐步放量到100%。

 

虽然这个过程中,没有主动同步数据到缓存,但是通过控制放量的节奏,保证了初始化缓存过程中,不会出现较大的耗时波动。

 

例如新上线的缓存逻辑,可以考虑逐渐灰度放量。

 

 
扫描数据库刷缓存

 

如果缓存维度是商品维度或者用户维度,可以考虑扫描数据库,提前预热部分数据到缓存中。

 

开发成本较高。除了开发缓存部分的代码,还需要开发扫描全表的任务。为了控制缓存刷新的进度,还需要使用线程池增加并发,使用限流器限制并发。这个方案的开发成本较高。

 

 
通过数据平台刷缓存

 

这是比较好的方式,具体怎么实现呢?

 

数据平台如果支持将数据库离线数据同步到Hive,Hive数据同步到Kafka,我们就可以编写Hive SQL,建立ETL任务。把业务需要被刷新的数据同步到Kafka中,再消费Kafka,把数据写入到缓存中。在这个过程中通过数据平台控制并发度,通过Kafka 分片和消费线程并发度控制 缓存写入的速率。

 

这个方案开发逻辑包括ETL 任务,消费Kafka写入缓存。这两部分的开发工作量不大。并且相比扫描全表任务,ETL可以编写更加复杂的SQL,修改后立即上线,无需自己控制并发、控制限流。在多个方面ETL刷缓存效率更高。

 

但是这个方案需要公司级别支持 多个存储系统之间可以进行数据同步。例如mysql、kafka、hive等。

 

除了首次上线,是否还有其他场景需要预热缓存呢?

 

需要预热缓存的其他场景

 

 
如果Redis挂了,数据怎么办

 

刚才提到上线前,一定要进行缓存预热。还有一个场景:假设Redis挂了,怎么办?全量的缓存数据都没有了,全部请求同时打到数据库,怎么办。

 

除了首次上线需要预热缓存,实际上如果缓存数据丢失后,也需要预热缓存。所以预热缓存的任务一定要开发的,一方面是上线前预热缓存,同时也是为了保证缓存挂掉后,也能重新预热缓存。

 

 
假如有大量数据冷启动怎么办

 

假如促销场景,例如春节抢红包,平时非活跃用户会在某个时间点大量打开App,这也会导致大量cache miss,进而导致雪崩。此时就需要提前预热缓存了。具体的办法,可以考虑使用ETL任务。离线加载大量数据到Kafka,然后再同步到缓存。

 

总结

 

  • 一定要预热缓存,不然线上接口性能和数据库真的扛不住。

  • 可以通过灰度放量,扫描全表、ETL数据同步等方式预热缓存

  • Redis挂了,大量用户冷启动的促销场景等场景都需要提前预热缓存。

 

作者丨五阳
来源丨稀土掘金:juejin.cn/post/7277461864349777972
dbaplus社群欢迎广大技术人员投稿,投稿邮箱:editor@dbaplus.cn
最新评论
访客 2023年08月20日

230721

访客 2023年08月16日

1、导入Mongo Monitor监控工具表结构(mongo_monitor…

访客 2023年08月04日

上面提到: 在问题描述的架构图中我们可以看到,Click…

访客 2023年07月19日

PMM不香吗?

访客 2023年06月20日

如今看都很棒

活动预告