「这是我参与2022首次更文挑战的第9天,活动详情查看:2022首次更文挑战」
3、缓存击穿
数据库服务器崩溃(2)
- 系统平稳运行过程中
- 数据库连接量瞬间激增
- Redis服务器无大量key过期
- Redis内存平稳,无波动
- Redis服务器CPU正常
- 数据库崩溃
问题排查
- Redis中某个key过期,该key访问量巨大
- 多个数据请求从服务器直接压到Redis后,均未命中
- Redis在短时间内发起了大量对数据库中同一数据的访问
问题分析
- 单个key高热数据
- key过期
解决方案(术)
-
预先设定
以电商为例,每个商家根据店铺等级,指定若干款主打商品,在购物节期间,加大此类信息key的过期时长
注意:购物节不仅仅指当天,以及后续若干天,访问峰值呈现逐渐降低的趋势
-
现场调整
- 监控访问量,对自然流量激增的数据延长过期时间或设置为永久性key
-
后台刷新数据
- 启动定时任务,高峰期来临之前,刷新数据有效期,确保不丢失
-
二级缓存
- 设置不同的失效时间,保障不会被同时淘汰就行
-
加锁 分布式锁,防止被击穿,但是要注意也是性能瓶颈,慎重!
总结
缓存击穿就是单个高热数据过期的瞬间,数据访问量较大,未命中redis后,发起了大量对同一数据的数据库问,导致对数据库服务器造成压力。应对策略应该在业务数据分析与预防方面进行,配合运行监控测试与即时调整策略,毕竟单个key的过期监控难度较高,配合雪崩处理策略即可
4、缓存穿透
恶意请求
我们的数据库中的主键都是从0开始的,即使我们将数据库中的所有数据都放到了缓存中。当有人用id=-1来发生恶意请求时,因为redis中没有这个数据,就会直接访问数据库,这就称谓缓存穿透
解决办法
- 在程序中进行数据的合法性检验,如果不合法直接返回
- 使用布隆过滤器
布隆过滤器简介
想要尽量避免缓存穿透,一个办法就是对数据进行预校验,在对Redis和数据库进行操作前,**先检查数据是否存在,如果不存在就直接返回。**如果我们想要查询一个元素是否存在,要保证查询效率,可以选择HashSet,但是如果有10亿个数据,都用HashSet进行存储,内存肯定是无法容纳的。这时就需要布隆过滤器了
布隆过滤器(英语:Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量(bit数组)和一系列随机映射函数(hash)。布隆过滤器可以用于检索一个元素是否在一个集合中
因为是基于位数组和hash函数的,所以它的优点是空间效率和查询时间都远远超过一般的算法。但缺点也很明显,那就是有一定的误识别率和删除困难。但是可以通过增加位数组的大小和增加hash函数个数来降低误识别率(只能降低,没法避免)
放入过程
布隆过滤器初始化后,位数组中的值都为0。当一个变量将要放入布隆过滤器时,会通过多个hash函数映射到位数组的各个位上,然后将对应位置为1
查询过程
查询依然是通过多个hash函数映射到位数组的各个位上,如果各个位都为1,说明该元素可能存在,注意是可能存在!!。但是如果通过映射后,位数组对应位上不为1,那么该元素肯定不存在
放入过程图解
比如我们的布隆过滤器位一个8位的位数组,并且有3个hash函数对元素进行计算,映射到数组中的各个位上
我们将字符串”Nyima”放入布隆过滤器中
接下来将字符串”Cpower”放入布隆过滤器中
查询过程图解
比如我们要查询字符串”Cpower”是否存在,通过3个hash函数映射到了位数组的三个位置上, 三个位置都为1,那么该字符串可能存在
比如我们要查询字符串”SWPU”是否存在,通过3个hash函数映射到了位数组的三个位置,发现有一个位置不为1,那么该字符串肯定不存在
比如我们要查询字符串”Hulu”是否存在,通过3个hash函数映射到了位数组的三个位置,发现所有位置都为1,但是我们前面并没有将字符串”Hulu”放入布隆过滤器中,所以这里发生了误判
增加位数组的大小和hash函数个数可以降低误判率,但是无法避免误判