【线上故障分析】深入理解缓存预热

标签: 线上 故障分析 理解 | 发表时间:2023-09-12 10:01 | 作者:他是程序员
出处:https://juejin.cn/tag/%E6%9E%B6%E6%9E%84

theme: condensed-night-purple

缓存不预热会怎么样?我帮大家淌了路。缓存不预热会导致系统接口性能下降,数据库压力增加,更重要的是导致我写了两天的复盘文档,在复盘会上被骂出了翔。

悲惨的上线时刻

事情发生在几年前,我刚毕业时,第一次使用缓存内心很激动。需求场景是虚拟商品页面需要向用户透出库存状态,提单时也需要校验库存状态是否可售卖。但是由于库存状态的计算包含较复杂的业务逻辑,耗时比较高,在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任务。离线加载大量数据到Mafka,然后再同步到缓存。

总结

  1. 一定要预热缓存,不然线上接口性能和数据库真的扛不住。
  2. 可以通过灰度放量,扫描全表、ETL数据同步等方式预热缓存
  3. Redis挂了,大量用户冷启动的促销场景等场景都需要提前预热缓存。

相关 [线上 故障分析 理解] 推荐:

【线上故障分析】深入理解缓存预热

- - 掘金 架构
缓存不预热会导致系统接口性能下降,数据库压力增加,更重要的是导致我写了两天的复盘文档,在复盘会上被骂出了翔. 事情发生在几年前,我刚毕业时,第一次使用缓存内心很激动. 需求场景是虚拟商品页面需要向用户透出库存状态,提单时也需要校验库存状态是否可售卖. 但是由于库存状态的计算包含较复杂的业务逻辑,耗时比较高,在500ms以上.

Hadoop集群硬盘故障分析与自动化修复

- - CSDN博客推荐文章
作者:Zhang, Haohao. 硬盘在服务器中起着至关重要的作用,因为硬盘里面存储的是数据,随着制造业技术的提高,硬盘的类型也在逐渐的改变. 对于硬盘的管理是IAAS部门的责任,但作为业务运维也需要懂得相关的技术. 有的公司采用LVM来管理硬盘,这样做方便扩缩容,也有的公司直接用裸盘来存数据,这样做的好处是不会因LVM而损失掉一部分硬盘I/O速度.

服务注册中心 | 记一次 Consul 故障分析与优化

- - 掘金后端
在微服务体系中,服务注册中心是最基础的组件,它的稳定性会直接影响整个服务体系的稳定性. 本文主要介绍了爱奇艺微服务平台基于 Consul 的服务注册中心建设方式,与内部容器平台、API 网关的集成情况,并重点记录了 Consul 遇到的一次故障,分析解决的过程,以及针对这次故障从架构上的优化调整措施.

泛型理解

- - ITeye博客
泛型不是协变的,例如下面的代码不是正确的. 之所以声明泛型方法,一般是因为您想要在该方法的多个参数之间宣称一个类型约束. 例如,下面代码中的ifThenElse()方法,根据它的第一个参数的布尔值,它将返回第二个或第三个参数:. 注意,您可以调用ifThenElse(),而不用显式地告诉编译器,您想要T的什么值.

理解inode

- - haohtml's blog
inode是一个重要概念,是理解Unix/Linux文件系统和硬盘储存的基础. 我觉得,理解inode,不仅有助于提高系统操作水平,还有助于体会Unix设计哲学,即如何把底层的复杂性抽象成一个简单概念,从而大大简化用户接口. 下面就是我的inode学习笔记,尽量保持简单. 理解inode,要从文件储存说起.

理解OAuth 2.0

- - 阮一峰的网络日志
OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版. 本文对OAuth 2.0的设计思路和运行流程,做一个简明通俗的解释,主要参考材料为 RFC 6749. 为了理解OAuth的适用场合,让我举一个假设的例子. 有一个"云冲印"的网站,可以将用户储存在Google的照片,冲印出来.

线上事故分析

- - 互联网 - ITeye博客
线上服务不定点的不能使用, 查日志发现resin服务正在重启. 由于resin所在的服务有web监控,如果web服务没有相应,则会重启resin服务. 那到底是什么导致了无法请求到web服务呢(60秒没有相应). 1, 首先查看相应的日志:. /data/logs/chewenwww/stdout.log   正常信息日志.

Kafka线上环境部署

- - ITeye博客
本章内容是如何规划 Kafka 服务器的相关内容. linux 效率优于 windows. 因为 I/O 模型和网络传输效率(sendfile). 1.性价比 JBID 优于 RAID. 2.使用机械盘完全可以满足 Kafka 集群的使用,SSD 更好. 1.尽量分配跟多的内存给操作系统的 page cache.

理解云计算

- 车东 - oneoo's 私家花园
  现在互联网最热门的关键字“云计算”,大大小小的公司纷纷加入到这块领域. 简单来说,目前的“云计算”主要分为:SaaS、PaaS和IaaS三大类.   其中SaaS云计算,为软件即服务的概念. 把传统客户端软件部署在互联网上,用户只需要一个浏览器就可以使用到软件的模式. 其实早在2000年就已经有B/S结构的软件服务,与现在所说的SaaS云计算相近,但此前的B/S结构软件服务,数据库等服务端是需要用户自行部署的,而非由软件提供商进行统一部署.