前言
来整理一下缓存雪崩、击穿和穿透的问题,这个问题在面试中常出现,不是瞎说,我已经遇到几次了
一、缓存雪崩
1.雪崩
- 什么是雪崩,某度给出的解释
雪崩 当山坡积雪内部的内聚力抗拒不了它所受到的重力拉引时,便向下滑动,引起大量雪体崩塌,人们把这种自然现象称作雪崩。
说白了就是一部分雪因不可抗力出现问题导致越来越多雪一起崩塌产生的现象
- 那什么是缓存雪崩
缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机
2. 设想一个场景
①系统平稳运行过程中,忽然数据库连接量激增
②应用服务器无法及时处理请求
③大量408(request timeout),500错误页面出现
④客户反复刷新页面获取数据
⑤数据库崩溃
⑥应用服务器崩溃
⑦重启应用服务器无效
⑧Redis服务器崩溃
⑨Redis集群崩溃
⑩重启数据库后再次被瞬间流量放倒
3. 故障分析
我们能看得出来这是一个雪崩现象,由于数据库连接剧增导致服务器响应过慢,而展现在客户端的场景就是页面出现错误,结合实际情况,当我们遇到页面404的时候我们的下意识反应就是刷新,但是这无疑是持续增加数据库连接数量,恶性循环,最终整个服务器就崩溃了
所以我们需要从根源解决问题,也就是为什么数据库连接会突然增加
4. 问题排查
-
我们都知道redis的是一种key-value的形式存储在内存中的,key在初始时是可以设置过期时间的,在这个场景中,系统在平稳运行就排除了系统故障,那数据库突然连接量增大的原因就是redis中大量的key在这段时间内过期
-
可以反过来验证一下,假设在一个商城系统中,用户都在访问展示在首页的各种商品,这个时候首页中的商品数据的key碰巧集中过期,那用户再访问商品详情的时候,系统在redis缓存中没有找到对应的key就会在数据库中查找,就会出现上述问题
5. 解决方案
①预先设定
以电商为例,每个商家根据店铺等级,指定若干款主打商品,在购物节期间,加大此类信息key的过期时长
②现场调整
监控访问量,对自然流量激增的数据延长过期时间或设置为永久性key
③后台刷新数据
启动定时任务,高峰期来临之前,刷新数据有效期,确保不丢失
④二级缓存
设置不同的失效时间,保障不会被同时淘汰就行
⑤加锁
分布式锁,防止被击穿,但是要注意也是性能瓶颈,慎重!
6.总结
总的来说:缓存击穿就是单个高热数据过期的瞬间,数据访问量较大,未命中redis后,发起了大量对同一数据的数据库访问,对数据库和服务器造成压力。应对策略应该在业务数据分析与预防方面进行,配合运行监控测试与即时调整策略,毕竟单个key的过期监控难度较高,还是要配合雪崩处理策略
二、 缓存击穿
击穿就不用解释了,字面意思,直接结合场景来看
1.设想这种场景
①系统平稳运行过程中
②数据库连接量瞬间激增
③Redis服务器无大量key过期
④Redis内存平稳,无波动
⑤Redis服务器CPU正常
⑥数据库崩溃
2. 故障分析
首先能看到根据场景设定第三条“Redis无大量key过期”就能看出来这次不是雪崩了,但是数据库的连接量依然瞬间增长导致压力剧增而崩溃,心机之蛙一直摸你肚子,没有大量key过期不代表没有key过期,那很有可能只有一个数据的key过期了,但是这条数据的访问量巨大
3.确诊
①Redis中某个key过期,该key访问量巨大
②多个数据请求从服务器直接压到Redis后,均未命中
③Redis在短时间内发起了大量对数据库中同一数据的访问
总而言之就两点:单个key高热数据(比如商城中的热卖商品),key过期
4.解决方案
(1)预先设定
以电商为例,每个商家根据店铺等级,指定若干款主打商品,在购物节期间,加大此类信息key的过期时长 注意:购物节不仅仅指当天,以及后续若干天,访问峰值呈现逐渐降低的趋势
(2)现场调整
监控访问量,对自然流量激增的数据延长过期时间或设置为永久性key
(3)后台刷新数据
启动定时任务,高峰期来临之前,刷新数据有效期,确保不丢失
(4)二级缓存
设置不同的失效时间,保障不会被同时淘汰就行
(5)加锁
分布式锁,防止被击穿,但是要注意也是性能瓶颈,慎重!
三、缓存穿透
话不多说上场景
1.场景设定
①系统平稳运行过程中
②应用服务器流量随时间增量较大
③Redis服务器命中率随时间逐步降低
④Redis内存平稳,内存无压力
⑤Redis服务器CPU占用激增
⑥数据库服务器压力激增
⑦数据库崩溃
2. 故障排查
-
Redis中大面积出现未命中
-
出现非正常URL访问
3.问题分析
-
获取的数据在数据库中也不存在,数据库查询未得到对应数据
-
Redis获取到null数据未进行持久化,直接返回
-
下次此类数据到达重复上述过程
-
出现黑客攻击服务器
4.解决方法*
(1)缓存null
对查询结果为null的数据进行缓存(长期使用,定期清理),设定短时限,例如30-60秒,最高5分钟
(2)白名单策略
提前预热各种分类数据id对应的bitmaps,id作为bitmaps的offset,相当于设置了数据白名单。当加载正常数据时放行,加载异常数据时直接拦截(效率偏低)
使用布隆过滤器(下面介绍)
(3)实施监控
实时监控redis命中率(业务正常范围时,通常会有一个波动值)与null数据的占比
非活动时段波动:通常检测3-5倍,超过5倍纳入重点排查对象
活动时段波动:通常检测10-50倍,超过50倍纳入重点排查对象
根据倍数不同,启动不同的排查流程。然后使用黑名单进行防控(运营)
(4)key加密
问题出现后,临时启动防灾业务key,对key进行业务层传输加密服务,设定校验程序,过来的key校验
例如每天随机分配60个加密串,挑选2到3个,混淆到页面数据id中,发现访问key不满足规则,驳回数据访问
四、布隆过滤器
参考 布隆过滤器
1.什么是布隆过滤器
布隆过滤器(Bloom Filter)是一种空间效率极高的概率型数据结构,它主要用于判断一个元素是否可能属于某个集合,而不支持直接获取集合中的所有元素。
布隆过滤器的基本结构是一个固定长度的位数组和一组哈希函数。
2.工作原理
(1)初始化时,位数组的所有位都被设置为0。
(2)当要插入一个元素时,使用预先设定好的多个独立、均匀分布的哈希函数对元素进行哈希运算,每个哈希函数都会计算出一个位数组的索引位置。
(3)将通过哈希运算得到的每个索引位置的位设置为1。
(4)查询一个元素是否存在时,同样用相同的哈希函数对该元素进行运算,并检查对应位数组的位置是否都是1。如果所有位都为1,则认为该元素可能存在于集合中;如果有任何一个位为0,则可以确定该元素肯定不在集合中。
(5)由于哈希碰撞的存在,当多位同时为1时,可能出现误报(False Positive),即报告元素可能在集合中,但实际上并未被插入过。但布隆过滤器不会出现漏报(False Negative),即如果布隆过滤器说元素不在集合中,则这个结论是绝对正确的。
3.应用场景
布隆过滤器因其高效的空间占用和快速查询能力,在许多大规模数据处理和高性能系统中得到广泛应用,以下是一些典型的使用场景,其中就有我们上述提到的缓存穿透问题的解决
(1)缓存穿透防护:
在分布式缓存系统如Redis或Memcached中,用于避免缓存穿透问题。当一个请求试图访问数据库中的某个不存在的键时,如果直接去数据库查询会增加数据库压力。通过在前端部署一个布隆过滤器,可以预先判断该键很可能不存在于数据库中,从而避免对数据库发起无效请求。
(2)重复数据检测:
在爬虫抓取网页或者日志分析中,用于URL去重,确保不会重复抓取相同的页面或记录。
在大数据处理中,比如在Hadoop等框架中,用来过滤掉重复的数据块或者记录,减少计算和存储负担。
(3)垃圾邮件过滤:
用于电子邮件系统的垃圾邮件地址库,快速判断收到的邮件是否可能来自已知的垃圾邮件发送者。
(4)实时监控与报警系统:
当大量事件流经系统时,可以用于快速识别并过滤出已知异常事件,降低报警系统误报率。
(5)推荐系统:
在个性化推荐系统中,用于快速排除用户已经浏览过或者不感兴趣的内容。
(6)数据库索引优化:
对于大型数据库,可以利用布隆过滤器作为辅助索引结构,提前过滤掉大部分肯定不在结果集中的查询条件,减轻主索引的压力。
(7)社交网络和互联网服务:
在社交网络中,用于快速检测用户上传的内容是否存在违规信息,或是检查用户ID、账号是否存在黑名单中。
(8)数据分析与挖掘:
在大规模数据清洗阶段,用来剔除重复样本或无效数据。
(9)网络安全:
网络防火墙和入侵检测系统中,用于过滤已知恶意IP或攻击特征。
五、总结
简单的来说
-
缓存雪崩就是redis中大量key过期,相当于一家店铺的所有供应商突然罢工
-
缓存击穿就是redis中热点数据的key突然过期,相当于一家店铺正在热卖的衣服的供应商突然罢工,虽说就他一家但也可以算得上是一击致命
-
缓存穿透就是非法访问,黑客攻击了,或者有几百万个熊孩子同时故意在url上乱改参数访问,出现大量redis和MySQL都无法找到的数据访问