一、Redis 缓存雪崩
- 出现场景
如果使用redis记录大量的热点数据,且过期时间为同一个常量,那么可能会出现大批的缓存数据会在同一时间或较短的时间区间内失效,redis会根据淘汰策略进行优化,如果数据量比较大会导致线程出现短暂的阻塞;另外,因为大量的缓存失效,会导致请求直接落在DB上,请求数较大情况下会直接导致数据库瘫痪,然后整个业务系统变为不可用状态
- 解决方案
针对这种情况,我们可以在设置过期时间时加上一个随机值,类似
redis.set(key, value, expiredTime + Math.random()*10000)
,这样设置就不会出现在短时间内大量缓存key失效的情况。
二、Redis 缓存穿透
- 出现场景
如果用户请求的热点数据本身是不存在的,比如id为-1,或者id=‘‘的数据,查询缓存不存在后会将请求直接打到DB上,最终在DB中也没有查到此数据,此时Redis缓存就是去了作用,搞并发的情况下会降低数据库性能,甚至瘫痪
- 解决方案
- 增加参数校验,拦截掉大量的非法参数请求;
- 缓存空值,因为数据库中本来就不存在这些数据,因此可以在第一次重建缓存时将value 记录为 null,下次请求时从Redis获取到 null 值直接返回(注意,要对redis查询的返回值进行严格校验,区分key不存在返回的空值和主动设置的空值null);
- 布隆过滤器,将DB中的热点数据加载至布隆过滤器中(布隆过滤器的特性:若在过滤器中存在,不一定真是存在;若不存在时,一定不存在),每次请求前先校验布隆过滤器是否存在该key,不存在的话直接return;
三、Redis 缓存击穿
- 出现场景
高并发请求同一个热点数据,在热点数据失效的瞬间,大量请求在缓存中没有命中会直接落在DB上进行查询,导致DB压力瞬间增加
- 解决方案
增加互斥锁,在第一个请求没有在缓存命中开始在DB进行查询并重加缓存时加上一个互斥锁,在缓存重建完成之前,对这同一热点数据的请求将会被互斥锁拦截,被拦截的这些请求根据业务需求,可以延时重试直到拿到数据或直接返回失败等; 热点数据不设置过期时间(不建议,随着热点数据的增加,无过期时间的key也越来越多,或导致Redis的存储压力增加)