1、缓存穿透
缓存穿透就是指在高并发的情况下大量的请求去查询一个不存在于缓存中的数据,导致这些请求都直接访问数据库,给数据库造成压力。例如:我存储在缓存中的key是数字类型(123),但是网络攻击者频繁地用字符串(abc)去获取缓存。导致永远都无法命中缓存,请求最终都打到数据库。而缓存的意义就是减轻数据库的压力。
解决办法
- 布隆过滤器
布隆过滤器是redis提供的一种数据结构。它可以在海量数据中(上千万)来判断当前值存不存在。
在查询缓存之前,先使用布隆过滤器判断请求的参数是否有效,如果无效则直接返回结果,避免无效请求绕过缓存直接访问数据库。布隆过滤器的准确率不是百分之百,如果没有查到,就说明确实不存在;如果查到了,那数据可能存在也有可能不存在。
2.空值缓存:
如果查询的数据不存在,将该空结果也缓存起来,设置一个较短的过期时间,这样下次相同的请求就可以直接从缓存中获取空结果,避免继续访问数据库。
- 异常处理:
对于查询不到的数据,可以通过抛出异常的方式进行处理,在服务层或者接口层捕获异常并返回给客户端,避免直接访问数据库。
2、缓存击穿
缓存击穿是指在高并发的情况下,某个热点数据过期或被删除,导致大量请求同时访问数据库。
例如,学校的官网数据是热点数据,在并发非常高的时候,比如说高考志愿填报的时候,官网数据缓存过期了。
解决方法
1、设置热点数据永不过期
对于一些非常高频的热点数据,不设置过期时间。并且开启定时任务定期查看缓存有没有被删除,如果缓存不存在了,就更新缓存。原因是不设置过期时间只能保证redis不会删,但是不能保证其他服务有没有可能删key。
3、缓存雪崩
缓存雪崩是指在某个时刻,缓存中大批量的数据同时失效或过期,导致大量的请求直接访问数据库。
缓存雪崩与缓存击穿区别:前者是大量key过期,后者是某个key过期。
解决方法
1、合理规划key的过期时间
均匀过期:给热点数据设置不同的过期时间,给每个key的失效时间加一个随机值;
设置热点数据永不过期:对于高频数据,不设置过期时间。
- 引入缓存预热:
在系统启动或者低峰期,可以将数据预先加载到缓存中,避免在高峰期同时大量的请求导致缓存雪崩。
- 使用多级缓存:
可以使用多级缓存来分散请求,减轻单一缓存的压力。例如,可以将热点数据放在内存缓存中,将非热点数据放在分布式缓存中,以及备份数据放在持久化存储中,这样即使某个缓存出现问题,仍然可以从其他级别的缓存中获取数据。
4、使用限流和熔断机制:
对于热点数据的请求,可以采用限流和熔断机制,控制并发请求的数量,避免大量请求同时访问缓存和数据库。
如果发现Redis服务宕机,导致数据库的负载压力增大,我们可以启动服务熔断机制,暂停对缓存服务的访问。但是这种方法对业务应用的影响比较大,我们也可以通过限流的方式降低这种影响。
例如业务系统正常运行时,请求入口每秒最大允许进入的请求数是1万个,其中9000请求个可以被缓存处理,余下1000个会发送给数据库处理。
一旦发生雪崩,数据库每秒处理的请求突然增加到1万个,此时我们就可以启动限流机制。在前端请求入口处,只允许每秒进入1000个请求,其他的直接拒绝掉。这样就可以避免大量并发请求发送给数据库。