缓存穿透、缓存击穿、缓存雪崩的区别以及解决方案
一.缓存穿透
缓存穿透是指缓存根本就不存在,比如请求不存在的id,因为缓存内不存在这这个id,请求会直达到数据库,如果恶意请求这个id就会导致数据库压力过大。
解决方案
-
参数合法值校验。比如要用手机号做搜索条件时,客户端却传了12位号码,则将请求直接过滤掉。
-
缓存空值。在数据库查询不到数据时,将null值放进缓存。
-
使用布隆过滤器。在访问缓存之前可以快速的知道这个key存不存在,不存在则拦截该请求。使用布隆过滤器因为hash值冲突,可能会存在误判的情况,布隆过滤器判定key存在的话,那么缓存可能存在这个key,如果判定key不存在的话,那么缓存内一定不存在这个key。
二.缓存击穿
缓存击穿与缓存穿透类似,是缓存存在这个key,但这个key失效了,导致一瞬间大量压力传达到数据库
解决方案
- 加锁。在key失效时,只能有一个请求到达数据库,同时更新缓存。
- 自动续期。假设一个缓存30分钟内失效,可以创建一个线程,在20分钟后更新缓存,将缓存的时限重新设置为30分钟。
- 缓存不失效。一些热门的key其实是可以不设置过期时间的,让其永久有效。比如秒杀活动的热门商品,由于这类商品id并不多,在缓存中我们可以不设置过期时间。在秒杀活动开始前我们可以进行缓存
预热
,等秒杀活动过一段时间后再手动删除掉这些缓存。
三.缓存雪崩
缓存雪崩是指一瞬间大量key同时失效(大量的key同时过期)或整个缓存不可用了(硬件问题、机房网络问题导致),导致大量的请求绕过缓存直接请求到了数据库。
解决方案
-
加时间随机数。避免缓存同时失效,在缓存过期时间内加上随机数。
-
高可用。配置redis哨兵模式或集群模式,避免单点redis故障导致整个缓存不可用的情况。
-
服务降级。预先配置默认数据,当一段时间内访问redis失败到达一定次数时,打开一个全局开关,给所有请求返回默认数据,同时开启一个定时任务,每过一段时间访问一次redis,直到在一定时间内能访问成功两次或以上后,关闭全局开关,恢复redis的访问。