缓存穿透、缓存击穿、缓存雪崩三者都是指在处理数据库请求时缓存失效,导致大量的请求都直接落到了数据库上,对数据库造成了巨大的压力甚至宕机。
而缓存失效的原因有多种,分为三种情况:
- 缓存和数据库都没有查询的Key
- 热点数据不在缓存中
- 大量缓存同时过期,或缓存服务器宕机
缓存穿透
大量使用缓存和数据库都没有的Key进行查询。
解决办法
- 缓存无效Key
- 缓存和数据库都查不到的key写到 Redis 中,并设置过期时间。
- 但是无法应对大量的不同的Key查询
- 布隆过滤器
- 通过布隆过滤器在大量数据中判断Key是否存在
- 数组中各元素默认值为0,在存储元素时,Key通过多个Hash函数计算Hash值对应的索引,相应位置设置为1
- 判断元素是否存在同样步骤判断相应位置是否全为1
缓存击穿
请求的 key 对应的是热点数据 ,该数据存在于数据库中,但不存在于缓存中(通常是因为缓存中的那份数据已经过期) 。
解决办法
- 设置热点数据永不过期或者过期时间比较长。
- 针对热点数据提前预热,将其存入缓存中并设置合理的过期时间比如秒杀场景下的数据在秒杀结束之前不过期。
- 请求数据库写数据到缓存之前,先获取互斥锁,保证只有一个请求会落到数据库上,减少数据库的压力。
缓存雪崩
- 缓存在同一时间大面积的失效。
- 另外,缓存服务宕机也会导致缓存雪崩现象。
解决办法
- 针对 Redis 服务不可用的情况:
- 采用 Redis 集群,避免单机出现问题整个缓存服务都没办法使用。
- 限流,避免同时处理大量的请求。
- 针对热点缓存失效的情况:
- 设置不同的失效时间比如随机设置缓存的失效时间。
- 缓存永不失效(不太推荐,实用性太差)。
- 设置二级缓存