缓存穿透
一般的缓存系统,都是按照key去缓存查询,如果不存在对应的value,就去后端系统查找(比如DB)。
一些恶意的请求会故意查询不存在的key,请求量很大,就会对后端系统造成很大的压力。这就叫做缓存穿透。
如何避免?
1:对查询结果为空的情况也进行缓存,这样,再次访问时,缓存层会直接返回空值。缓存时间设置短一点,或者该key对应的数据insert了之后清理缓存。
2:对一定不存在的key进行过滤。具体请看布隆过滤器
缓存击穿
是针对缓存中没有但数据库有的数据。
场景是,当Key失效后,假如瞬间突然涌入大量的请求,来请求同一个Key,这些请求不会命中Redis,都会请求到DB,导致数据库压力过大,甚至扛不住,挂掉。
解决办法
1、设置热点Key,自动检测热点Key,将热点Key的过期时间加大或者设置为永不过期,或者设置为逻辑上永不过期
2、加互斥锁。当发现没有命中Redis,去查数据库的时候,在执行更新缓存的操作上加锁,当一个线程访问时,其它线程等待,这个线程访问过后,缓存中的数据会被重建,这样其他线程就可以从缓存中取值。
缓存雪崩
是指大量Key同时失效,对这些Key的请求又会打到DB上,同样会导致数据库压力过大甚至挂掉。
解决办法
1)让Key的失效时间分散开,可以在统一的失效时间上再加一个随机值,或者使用更高级的算法分散失效时间。
2)构建多个redis实例,个别节点挂了还有别的可以用。
3)多级缓存:比如增加本地缓存,减小redis压力。
4)对存储层增加限流措施,当请求超出限制,提供降级服务(一般就是返回错误即可)