Redis缓存穿透与雪崩
使用缓存的问题
Redis 缓存的使用,极大的提升了应用程序的性能和效率,特别是数据查询方面。
但同时,它也带来了一些问题。其中,最要害的问题,就是数据的一致性问题,从严格意义上讲,这个问题无解。
如果对数据的一致性要求很高,那么就不能使用缓存。
另外的一些典型问题就是,缓存穿透、缓存雪崩和缓存击穿。目前,业界也都有比较流行的解决方案。
使用缓存的逻辑
查询一个数据,如果缓存中存在,则返回数据
缓存中不存在,到数据库中查询
数据库中存在,返回数据,且存到缓存
数据库中不存在,返回空值
缓存穿透
数据库和缓存中都没有,这样缓存无法拦截,也无法在数据库中查询到存到缓存中,
每次查询都直达数据库,给数据库造成很大压力,即穿透
解决方案
-
布隆过滤器
是一种数据结构,将所有要查询的参数以hash的形式存储
在控制层进行校验,不符合则丢弃,从而避免了对底层存储系统的查询压力。 -
缓存空对象
当查询的数据不存在时,从数据库返回的空值也存到缓存里,同时设置一个过期时间
这种方法存在两个问题:- 缓存需要更多的空间来存储,这里可能会有很多空值
- 即使设置了过期时间,仍然会有一段时间,缓存和数据库中的数据不一致,这对需保持一致性的业务有影响
缓存击穿
指一个key是热点数据,大并发的集中对这一个key进行访问
这个key过期的瞬间,持续的大并发就穿破缓存,直接请求数据库,同时回写缓存,这时给数据库造成很大压力
解决方案
- 设置热点数据永不过期
- 加互斥锁
分布式锁:保证对于一个key只有一个线程能够去查询后端服务,其他没有获得分布式锁权限的只能等着
缓存雪崩
指某个时间段,缓存集中过期失效,于是所有的请求都会达到存储层,集中创建缓存,存储层的调用量会暴增,造成周期性压力。
致命的缓存雪崩,是缓存服务器某个节点宕机或断网。会对数据库造成不可估计的压力
解决方案
-
搭建集群
多增设几台Redis服务,实现Redis的高可用 -
限流降级
通过加锁来限制向数据库查数据并写入缓存的线程数量 -
数据预热
在正式部署之前,把所有可能访问的数据访问一遍,这样部分可能大量访问的数据就会加载到缓存中。
-
给不同的key设置随机的TTL值,防止其一起过期