缓存穿透
现象
- 应用服务器压力突然变大
-
redis命中率降低
-
一直查询数据库
原因
-
redis查询不到数据了
-
出现了很多非正常的url访问
key对应的数据在数据源并不存在,每次针对此key的请求从缓存获取不到,请求都会压到数据源,从而可能压垮数据源。比如用一个不存在的用户id获取用户信息,不论缓存还是数据库都没有,若黑客利用此漏洞进行攻击可能压垮数据库。
解决方案
- 对空值缓存
不管一个查询查询到的数据是否存在都进行缓存,即使为空。设置空的过期时间很短,不超过5分钟。 -
设置白名单
使用bitmaps类型定义一个可以访问的名单,名单id作为bitmaps的偏移量,每次访问和bitmap里面的id进行比较,如果访问id不在bitmaps里面,进行拦截,不允许访问。 -
使用布隆过滤器
布隆过滤器可用于检索一个数据是否在一个集合中,他的优点是时间和空间都超过一搬的算法。缺点是有一定的概率误识别和删除困难。
将所有可能存在的数据hash到一个足够大的bitmaps中,一个一定不存在的数据会被bitmaps拦截掉。从而避免对底层存储系统的查询压力。
缓存击穿
现象
-
数据库中访问压力瞬间增加
-
redis没有出现大量key过期
-
redis正常 运行
原因
- redis中某个key过期了,大量使用这个key
解决方案
-
预先设置热门数据:在redis高峰访问之前,吧一些热门数据提前存入到redis里面,加大这些热门数据key的时长
-
实时调整:现场监控哪些数据热门,实时调整key的 过期时长
-
使用锁
- 在缓存失效 的时候(判断拿出来 的值为空),不是立即去load db
-
先使用缓存工具的某些带成功操作返回值的操作(比如redis的setnx)去set一个mutex key。
-
当操作返回成功时,再进行load db的操作,并回设缓存,最后删除mutex key.
-
当操作返回失败,说明有其他线程在load db,当前线程睡眠一段时间再重试整个get缓存的方法。
缓存雪崩
现象
- 数据库压力变大,服务器崩溃
原因
- 在极少的时间内,出现了大量key集中过期的情况
压垮骆驼的最后一根稻草。
key对应的数据存在,但在redis中大量过期,若此时有大量请求进来,这些请求发现缓存过期后会从后端db加载数据,并会设到缓存。这时候如果大并发的请求可能会瞬间把后端db压垮。
解决方案
- 设置多级缓存:nginx缓存,redis缓存,其他缓存
-
使用锁或者队列,用加锁的方式来保证不会有大量线程对数据库进行一次性读写,从而避免缓存失效的时候大量请求落在db上。不适用于高并发情况。
-
记录缓存数据是否过期,(设置提前量),如果过期,会触发通知另外的线程在后台去更新实际key的缓存。
-
将缓存失效时间分散开,可以在原有的时间上加上1-5分钟的随机值。这样每一个缓存过期时间的重复率就会降低。就很难引发集体失效。
区别
缓存雪崩和缓存击穿的区别
定义和原因:
缓存击穿:指在使用缓存系统时,当某个特定的热点数据失效,并且在该数据失效的时候有大量的请求同时涌入,超过了缓存的承载能力,导致请求直接绕过缓存查询后端数据源,给后端系统带来过大的压力。
缓存雪崩:指在使用缓存系统时,缓存中的大量数据同时失效(例如缓存中的数据过期或缓存系统崩溃),导致大量请求直接访问后端存储系统,给后端系统带来巨大的负载压力。
原因不同:
缓存击穿的原因是针对某一个特定的热点数据失效引起的,当该数据失效时,大量请求同时访问,导致缓存无法提供服务。
缓存雪崩的原因是缓存中的大量数据失效,可以是同时过期或缓存系统故障,导致大量请求直接访问后端存储系统。
影响范围不同:
缓存击穿通常只涉及到某个特定的热点数据,其他数据的缓存不受影响。
缓存雪崩会影响到缓存中大量数据,导致整个系统的性能下降,甚至可能导致系统瘫痪。
解决方法不同:
缓存击穿的常见解决方法包括设置热点数据的永不过期策略、使用互斥锁等。
缓存雪崩的常见解决方法包括错开缓存数据的过期时间、引入多级缓存、实施熔断机制等。