Redis作为缓存使用时,可能会面临击穿、穿透、雪崩等问题。

击穿

Redis击穿:当Redis的1个key过期了或者LRU/LFU算法淘汰了,此时大量并发请求这个key,因为此时redis中并没有这个key,所以这些请求会打到后面的数据库(mysql)上,以至于数据库的压力太大。

避免缓存击穿的思路——避免key过期、防止大量请求打到数据库上.。

  • 热点数据可以设置为永不远期
  • 让这些请求进行setnx lock(获取锁),获取成功的请求去访问数据库,访问成功后放在Redis缓存上,其余请求从缓存取值即可。
    • 为避免拿到锁的请求因为其他原因没有去取数据而又不释放锁,所以给锁加上过期时间,避免死锁问题
    • 为避免给锁加的时间太短(访问数据库阻塞需等待),因此采用多线程(守护线程),监控锁的生存时间,便于必要时及时更新锁的时间

image.png

穿透

当请求了一个数据库不存在(Redis缓存中自然不存在)的数据时,此时请求会直接去请求数据库查询不存在的数据,占用数据库性能,浪费资源。

  • 避免缓存穿透的思路,对请求数据进行过滤,可使用Bloom过滤器(Bloom不能删除),布谷鸟过滤器等。
  • 从DB中查询出来数据为空,也进行空数据的缓存,避免每次都进行数据库查询;

image.png

雪崩

缓存雪崩,是Redis缓存中Key批量过期,此时大量请求压力给到数据库。

  • 如果缓存失效和时间点无关,那么可以采用给key设置随机过期时间
  • 如果缓存时间和时间点相关(比如0点缓存失效更新),此时依旧采取并免缓存击穿思路,避免大量请求压力给到数据库,一种做法和避免缓存击穿相同,设置锁;另一种做法是业务设置这个时间点做一个延迟,以便新数据加载进Redis中。

image.png