看完这篇,让你吃透 Redis 的缓存穿透、缓存击穿、缓存雪崩问题

缓存的基本使用

看完这篇,让你吃透 Redis 的缓存穿透、缓存击穿、缓存雪崩问题

  1. 前端向后台发送请求
  2. 判断 Redis 中是否存在
  3. 假如存在,Redis 直接返回数据,然后返回给前端(end)
  4. 假如不存在,服务端发起请求查询数据库
  5. 接收到返回的数据后,更新到 Redis 缓存,保证下次能获取到
  6. 返回数据给前端(end)

缓存穿透

问题描述

  1. 用户发起大量的请求
  2. 结果发现 Redis 中没有数据
  3. 后台查询数据库,发现数据库也没有数据
  4. 就这样一直请求,导致数据库崩溃

这种大量的请求,可能是接口本身的并发量就比较大,也可能是有黑客在攻击

解决方案

1. 异常参数校验

比如发起一个 id 为 “-1” 的请求,这一看就是有问题的,哪有可能 id 为负数的。或者一些非空参数,传了空值,极有可能是某人在发起攻击,直接后台判断拦截

优点: 最快,也是最简单的拦截方式,没有额外的资源开销

缺点: 适用的场景有限

2. 空值缓存

看完这篇,让你吃透 Redis 的缓存穿透、缓存击穿、缓存雪崩问题

  1. 直接跳到判断 Redis 是否存在
  2. 不存在,缓存空数据,设置过期时间一般为 30 秒(这里的空数据,可以直接设置数据为空的情况的值,也可以是空值标识,过期时间根据业务需求调整)
  3. 服务端直接返回前端

优点: 数据为空时能够快速返回,不需要将压力落到数据库上,避免了数据库压力过大,甚至崩溃的情况

缺点: 缓存层和存储层的数据会有一段时间窗口的不一致,就是数据库明明没值,缓存上却有值,一致性要求高的业务需要注意,做好校验工作

3. 布隆过滤器

假如我们添加值到布隆过滤器中,布隆过滤器会通过计算多种不同的哈希函数来计算出多个 hash 值,然后将对应位置的值设置为 1。因此这个 hash 值是有被多个不同的值对应的可能,所以说布隆过滤器如果命中了说明值可能存在,如果不命中肯定不存在误判率为3%

看完这篇,让你吃透 Redis 的缓存穿透、缓存击穿、缓存雪崩问题

  1. 直接跳到判断 Redis 是否存在
  2. 不存在,则从布隆过滤器中获取
  3. 将获取到的值,更新到 Redis(首先布隆过滤器存在值,也不一定是正确的,因此并非所有场景都适用,其次数据需要刷回 Redis,因为 Redis 没值依然会来布隆过滤器上取值,因此数据本身需要对正确性的要求不是很高)
  4. 服务端返回数据

优点:

  1. 等同于用布隆过滤器代替了数据库,因此性能高
  2. 由于顶替了数据库,规避了数据库宕机的风险

缺点:

  1. 代码逻辑较为复杂
  2. 需要对布隆过滤器预先做初始化
  3. 布隆过滤器的初始化与更新较为复杂
  4. 布隆过滤器不支持删值操作
  5. 适用场景有限,由于布隆过滤器获取的数据存在不正确的可能性,因此需要数据对本身值的正确性要求较低,适用于注重数据是否存在的场景,比如:IP 访问白名单,之前是否访问过;垃圾邮件,垃圾短信过滤等

缓存击穿

问题描述

  1. 用户发起大量的请求
  2. 这时 Redis 中数据大量过期
  3. 导致瞬间数据库压力暴增,导致数据库宕机

解决方案

1. 设置热点数据永远不过期

也是一种方法,但是总感觉心里不太安心

2. 设置热点数据的存活时间较长,且分布均匀的岔开过期时间

很好理解,存活时间长自然降低了出现大量过期的频率
使用随机数岔开过期时间,使得需要过期的数据先后过期,使得数据库有充足的时间处理过期的数据

3. 限流做安全保障

举个例子:比如一个商场,双 11 我需要大批量的替换图片,这时候如果大量的失效必然会导致数据库崩溃,这时如果有做限流控制,就可以针对获取图片的接口进行限流,等到都替换完,再将限流放开。

缓存雪崩

问题描述

Redis 层由于压力过大,导致 Redis 服务器宕机,所有后端请求直接落在数据库上,导致数据库也宕机。
看完这篇,让你吃透 Redis 的缓存穿透、缓存击穿、缓存雪崩问题

解决方案

1. Redis 高可用

顾名思义,通过多台的 Redis 架设集群,分摊压力

Redis + Cluster 分布式水平扩展高可用集群

2. 限流

通过限制访问数量的方式,防止大量的请求进入缓存,可以通过限制 IP 频率,限制请求总量,或者使用消息队列依次处理请求等方式