一:缓存穿透
1:概念
举个栗子,当用户查询一个数据,首先查redis内存数据库发现没有,即缓存没命中。于是向持久层数据库(mongo,mysql等)查询,发现也没有,于是本次查询失败。当用户很多的时候,缓存都没有命中,于是都去请求了持久层数据库。这会给持久层数据库造成很大的压力,这就是缓存穿透。
2:解决方案
缓存空对象:
当持久层数据库不命中后,即使返回的空对象也将其缓存起来,同时设置过期时间,之后再访问这个数据将会从缓存层中获取,不再访问持久层数据库,减少了数据库压力。不过这个有个场景会适得其反,假如黑客每次请求都生成不同的唯一ID(例如UUID),那缓存中就会大量缓存没有价值的key保存空对象,占用大量资源,并且还会触发缓存淘汰策略,将有价值的缓存key淘汰掉。布隆过滤器(Bloom Filter):
在查询数据库之前,先在布隆过滤器查询,如果查询不存在,就可以不用去查数据库了,从而避免了缓存穿透,减少了数据库压力。推荐使用这种方式。布隆过滤器 BloomFilter - Redis缓存穿透的天敌
二:缓存击穿
是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求持久层数据库,就像在一个屏障上凿开了一个洞。
三:缓存雪崩
1:概念
缓存层出现了错误,不能正常工作了。于是所有的请求都会达到存储层,存储层的调用量会暴增,造成存储层也会挂掉的情况。
其实大量机器挂掉,大批量缓存数据同时失效都属于雪崩。
2:解决方案
搭建集群 redis cluster,实现高可用。
即使一台Redis挂掉,其他Redis机器仍然还可以继续工作。限流降级。
这个解决方案的思想是,在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。数据预热。
数据加热的含义就是在正式部署之前,我先把可能的数据先预先访问一遍,这样部分可能大量访问的数据就会加载到缓存中。在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。