首页 > 作文

架构思维之缓存雪崩的灾难复盘

更新时间:2023-04-04 21:14:31 阅读: 评论:0

目录
1 真实案例1.1 背景1.2 问题处理2 缓存雪崩2.1 概念2.2 解决方案分析2.2.1 缓存集群+数据库集群2.2.2 适当的限流、降级2.2.3 随机过期时间2.2.4 缓存预热3 缓存穿透3.1 概念3.2 解决方案分析3.2.1 缓存空值3.2.2 bloomfilter3.2.3 两种方案的选择判断4 缓存击穿4.1 概念4.2 解决方案4.2.1 锁的方式4.2.2 空初始值

1 真实案例

云办公系统用户实时信息查询功能优化发布之后,系统发生宕机事件(系统挂起,页面无法加载)。

1.1 背景

我们im原有的一个功能,当鼠标移动到用户头像的时候,会显示出用户的基本信息。信息比较简单,只包含简单的用户名、昵称、性别、邮箱、电话等基本数据,

这是一个典型的数据查询,大概过程如下左侧,访问用户基本信息的时候会先去redis中查一下,如果不存在,就把大约2w左右的用户数据一次性取出来,保存在redis中,因为用户基本信息在同一张表上,用户信息表的数据量也很少,所以一直也没什么问题。

过程如下图左侧所示。

后续对功能做了优化,原有采集的信息除了用户的基本信息之外,还采集了教育经历、工作经历、所获勋章等。

这些信息存储在不同的表里面,所以采集过程是一个复杂的联表查询,特别是有些基础表数据量比较大,执行效率也是比较慢的。

如果把所有用户全部取出来并存储在一个redis节点中,明显已经不适用,一个是批量查询导致数据库执行效率慢,一个是redis单节点数据太大。

所以开发同学做了下优化,每次只取单个用户的综合信息存在redis中,一个用户建一个缓存,如上图右侧所示。

1.2 问题处理

这种做法看着没啥问题,当晚发布后,在第二天的上午10点~11点就发生了系统瓶颈卡顿,最后挂起的情况,数据库的内存、cpu全部飙上去了。

第一时间的处理方法是降级,程序回滚到之前只提供基本信息的阶段,其他的前端默认显示空信息。接着就是对问题进行分析了,后确认原因是产生了 缓存雪崩了。

新发布的系统,缓存池是空的,在早上10点高峰期的时候,大量的人员到im上进行访问,系统开始初次建立每个人的缓存信息,大量的请求查询不到缓存,直接透过缓存池投向数据库,造成瞬时db请求量井喷。这是典型的缓存雪崩了。

同时因为,失效时间相近(8小时失效),所以也有潜在的缓存雪崩。

应急处理方案:适当处理缓存的机制会议方案,采用布隆过滤器、空初始值、随机缓存失效时间方式来预防缓存击穿和缓100以内的合数存雪崩的产生。

最终解决方案:改回原来缓存全公司员工信息的方式,根据执行计划和slowlog,优化获取员工信息的sql脚本,去掉不需要的字段和无意义的连接。

2 缓存雪崩

2.1 概念

缓存雪崩是指大量的key设置了相同的过期时间,导致在缓存在同一时刻全部失效,造成瞬时db请求量大、压力骤增,引起雪崩。

上面的哪个问题,初次访问的数据都是未建立缓存的,跟同时失效的情况一样,当峰值期到来的时候,会大量的请求查询不到缓存,直接透过缓存池投向数据库,造成瞬时db请求量井喷。

2.2 解决方案分析

2.2.1 缓存集群+数据库集群

在系统容量设计的时候,应该能够预见后期会有大量的请求,所以在发生雪崩前对缓存集群实现高可用,如果是使用 redis,可以使用 主从+哨兵 ,redis cluster 来避免 redis 全盘崩溃的情况。

同样的,也需要对数据库进行高可用保障,因为透过缓存之后,真正考验的是数据库的抗压能力。所以 1主n从 甚至 数据库集群 是我们需要重点去考虑的。

2.2.2 适当的限流、降级

可以使用 hystrix进行限流 + 降级,比如像上面那种情况,一下子来了1w个请求,不是当前系统的吞吐能力能够承受的,假设单秒tps的能力只能是 5000个,那么剩余的 5000 请求就可以走限流逻辑。

可以设置一些默认值,然后调用我们自己降级逻辑去fallback,保护最后的 mysql 不会被大量的请求挂起。除了hystrix之外,阿里的ntinel 和 google的ratelimiter 都是不错的选择。

ntinel 漏桶算法

ratelimiter 令牌桶算法

另外可以考虑使用用本地缓存来进行缓冲,在 redis cluster 不可用的时候,不至于全线崩溃。

2.2.3 随机过期时间

可以给缓存设置过期时间时加上一个随机值时间,使得每个key的过期时间分布开来,不会集中在同一时刻失效。

随机值我们团队的做法是:n * 3/4 + n * random() 。所以,比如你原本计划对一个缓存建立的过期时间为8小时,那就是6小时 + 0~2小时的随机值。

这样保证了均匀分布在 6~8小时之间。如图:

2.2.4 缓存预热

类似上面的那个案例,并不是还没过斯洛伐克旅游期,而是新功能发布,压根还没建设过缓存,所以可以在峰值期之前先做好部分缓存,避免瞬时压力太大。

所以如果10点是峰值期,那么可以预先在8~10点期间,可以逐渐的把大部分缓存建立起来。如图:

3 缓存穿透

3.1 概念

缓存穿透是指访问一个不存在的key,缓存不起作用,请求会穿透到db,流量井喷时会导致db挂掉。

比如 我们查询用户的信息,程序会根据用户的编号去缓存中检索,如果找不到,再到数据库中搜索。如果你给了一个不hope的意思存在的编号:xxxxxxxx,那么每次都比对不到,就透过缓存进入数据库。

这样风险很大,如果因为某些原因导致大量不存在的编号被查询,甚至被恶意伪造编号进行攻击,那将是灾难。

3.2 解决方案分析

3.2.1 缓存空值

发生穿透的原因是缓存中没有存储这些空数据的key,或者压根这个数据的key是不会存在的,从而导致每次查询都进入数据库中。

我们就可以将这些key的值设置为null,并写到缓存池中。后面再出现查询这个key 的请求的时候,直接返回null,这样就在缓存池中就被判断返回了,压力在缓存层中,不会转移到数据库上。

3.2.2 bloomfilter

我们称作布隆过滤器,bloomfilter 类似于一个hba t 用来判断某个元素(key)是否存在于某个集合中。

这种方式在大数据场景应用比较多,比如 hba 中使用它去判断数据是否在磁盘上。还有在爬虫场景判断url 是否已经被爬取过。

这种方案可以加在第一种方案中,在缓存之前在加一层 bloomfilter ,把存在的key记录在bloomfilter中,在查询的时候先去 bloomfilter 去查询 key 是否存在,如果不存在就直接返回,存在再走查缓存 ,投入数据库去查询,这样减轻了数据库的压力。

流程图如下:

3.2.3天净沙秋思原文 两种方案的选择判断

前面说过,可能会存在一些恶意攻击,伪造出大量不存在的key,这种情况下如果我们如果采用缓存空值的办法,就会产生大量不存在key的null数据。显然是不合适的,这时我们完全可以使用第二种方案进行过滤掉这些key。

所以,判断的依据是:

针对key非常多、请求重复率比较低的数据,我们就没有必要进行缓存,使用bloomfilter直接过滤掉。

而对于空数据的key有限的,重复率比较高的,我们则可以采用缓存空值的办法进行处理。

4 缓存击穿

4.1 概念

一个存在的key,在缓存过期的一刻,同时有大量的请求,这些请求都会击穿到db,造成瞬时db请求量大、压力骤增。(注意跟上面两种的区别)

4.2 解决方案

4.2.1 锁的方式

分布式锁场景,在访问key之前,采用tnx(t if not exists)来设置另一个短期key来锁住当前key的访问,访问结束再删除该短期key。

这种现象是多个线程同时去查询数据库的这条数据,那么我们可以在第一个查询数据的请求上使用一个 互斥锁来锁住它。

其他的线程走到这一步拿不到锁就等着,等第一个线程查询到了数据,然后做缓存。后面的线程进来发现已经有缓存了,就直接走缓存。

锁不好的地方就是在其他线程在拿不到锁的时候就等待,这个会造成系统整体吞吐量降低,用户体验度也不好。

4.2.2 空初始值

这是一种短暂降级的方式:

如果一个缓存失效的时候,有无数个请求狂奔而来,而第一个请求从进入缓存池,判空,再到数据库检索,再查询出结果并返回设置缓存的这个过程里,缓存是不存在的。

这个就很危险,超高并发下这个短暂的过程足已让千千万万请求投向数据库。更别提这可能是个慢查询,整个过程可能长达2s以上,那对数据库是一种非常大的伤害。

业内有一种做法叫做空初始值,短暂的局部降级来保证整个数据库系统不被击穿。大概流程如下:

可以看出,整个过程中我们牺牲了a、b、c、d的请求,他们拿回了一个空值或者默认值,但是这局部的降级却保证整个数据库系统不被拥堵的请求击穿。

这也是我面试中最喜欢问候选人的缓存类问题。

以上就是架构思维之缓存雪崩的灾难复盘的详细内容,更多关于缓存雪崩灾难的资料请关注www.887551.com其它相关文章!

本文发布于:2023-04-04 21:14:29,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/7155ec3f44282d3d52fa7a0af612bc09.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:架构思维之缓存雪崩的灾难复盘.doc

本文 PDF 下载地址:架构思维之缓存雪崩的灾难复盘.pdf

标签:缓存   数据库   数据   用户
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图