缓存雪崩

什么是缓存雪崩呢

就是数据未加载到缓存中,或者缓存同一时间大面积的失效,从而导致所有请求都去查数据库,导致数据库CPU和内存负载过高,甚至宕机。假设一万个请求同时打到你的数据库,那么你的数据库不用想肯定给搞死了,这就是缓存雪崩

一个缓存雪崩发过程

  1. redis集群大面积故障
  2. 缓存失效,但依然大量请求访问缓存服务redis
  3. redis大量失效后,大量请求转向到mysql数据库
  4. mysql的调用量暴增,很快就扛不住了,甚至直接宕机
  5. 由于大量的应用服务依赖mysql和redis的服务,这个时候很快会演变成各服务器集群的雪崩,最后网站彻底崩溃。

如何解决缓存雪崩

  • 第一种方案: 缓存层设计成高可用,防止缓存大面积故障。即使个别节点、个别机器、甚至是机房宕掉,依然可以提供服务,例如 Redis Sentinel 和 Redis Cluster 都实现了高可用。

  • 第二种方案:在批量往Redis存数据的时候,把每个Key的失效时间都加个随机值就好了,这样可以保证数据不会在同一时间大面积失效,我相信,Redis这点流量还是顶得住的。

  • 第三种方案:设置随机数,防止缓存同时失效

redisUtils.set(RedisKeys.App.appApiFrontHomePageOrg(),homePageOrgDTOList,RedisUtils.FRONT_END_EXPIRE+RandomUtil.randomInt(1,100)*100);
  • 第四种方案:加互斥锁。当发现没有命中Redis,去查数据库的时候,在执行更新缓存的操作上加锁,谁拿到锁谁去更新,同时在拿到锁之后先从缓存再获取一次如果有就返回,没有就查库然后更新(这种方案其实也是可以的)
<!-- redis所需 (自带lettuce 5.1.4.RELEASE) lettuce是springboot2.x后连接redis推荐使用的客户端 -->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

缓存击穿

什么是缓存击穿

我个人理解 击穿 就是正面刚 比如我是矛 你是盾 我直接把你的盾击穿, 就是比如 几个热点Key 同时几百万并发直接把redis 干掉了, 然后数据全部打到数据库的情况,或者是redis的这几个热点数据失效的情景下,同时全部的并发查这个热数据,导致最后打到数据库的情况 这个就是缓存击穿。

### 如何解决缓存击穿

  • 还是分布式锁 哈哈 因为分布式锁能控制到数据库的最后一到防线
  • redis做集群 哨兵 (下一篇讲)

缓存穿透

什么是缓存穿透

缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。

### 如何解决缓存穿透

  1. 第一种方案 和上面的双重锁一样 如果是拿到数据库为空 那么就给这个key 设置一个null值 时间设置短一点 30s, 这样下次并发进来就不会说把数据打到我们的数据库上了
redisTemplate.opsForValue().set(key,"byId",30,TimeUnit.SECONDS);

就是我们写代码的时候 要对一些非法的请求参数校验 我相信大家都是这样做的。

Q.E.D.


知道的越多,不知道的越多