Redis三大缓存问题及解决方法(雪崩、击穿、穿透)

avatar
作者
猴君
阅读量:1

redis缓存问题及解决方法

缓存雪崩

当大量缓存数据在同一时间过期(失效)或者Redis故障宕机时,如果此时有大量的用户请求,都无法在Redis中处理,于是全部请求都直接访问数据库,从而导致数据库的压力骤增,严重的会造成数据库宕机,从而形成一系列连锁反应,造成整个系统崩溃,这就是缓存雪崩的问题。

717343a0da7a1b05edab1d1cdf8f28e5

导致原因

  • 大量数据同时过期;
  • Redis 故障宕机;

常见解决方法

针对大量数据同时过期而引发的缓存雪崩问题,常见的应对方法有下面这几种

  1. 设置过期时间
    大量的数据设置不同的过期时间,避免同时过期。也可以选择给过期时间加上一个随机数,这样就可以不会在同一时间过期。

  2. 互斥锁
    发现访问的数据不在Redis中,加上互斥锁,保证同一时间内只有一个请求来构建缓存( 从数据库读取数据,再将数据更新到 Redis 里),当缓存构建完成后,再释放锁。未能获取互斥锁的请求,要么等待锁释放后重新读取缓存,要么就返回空值或者默认值。

​ 实现互斥锁的时候,最好设置超时时间,不然第一个请求拿到了锁,然后这个请求发生了某种意外而一直阻塞,一直不释放锁,这时 其他请求也一直拿不到锁,整个系统就会出现无响应的现象。

针对 Redis 故障宕机而引发的缓存雪崩问题,常见的应对方法有下面这几种

  1. 服务熔断或请求限流机制

    启动 服务熔断 机制,暂停业务应用对缓存服务的访问,直接返回错误,暂停使用数据库,等Redis恢复正常后,在允许业务应用缓存服务。

    启动 请求限流 机制,只将少部分请求发送到数据库进行处理,再多的请求就在入口直接拒绝服务

  2. 构建Redis缓存高可靠集群

    服务熔断或请求限流机制是缓存雪崩发生后的应对方案,我们最好通过主从节点的方式构建 Redis 缓存高可靠集群

    如果 Redis 缓存的主节点故障宕机,从节点可以切换成为主节点,继续提供缓存服务,避免了由于 Redis 故障宕机而导致的缓存雪崩问题。

缓存击穿

如果缓存中某个热点数据过期了,此时大量的请求访问了该热点数据,就无法从缓存中读取,直接访问数据库,数据库很容易被高并发的请求冲垮,这就是缓存击穿问题。

缓存击穿跟缓存雪崩很相似,也可以认为缓存击穿是缓存雪崩的一个子集

图片

常见解决方法

  • 互斥锁方案,保证同一时间只有一个业务线程更新缓存,未能获取互斥锁的请求,要么等待锁释放后重新读取缓存,要么就返回空值或者默认值。
  • 不给热点数据设置过期时间,由后台异步更新缓存,或者在热点数据准备要过期前,提前通知后台线程更新缓存以及重新设置过期时间;

缓存击穿和缓存雪崩的区别

缓存雪崩:在某一个时间段,缓存数据同时失效。导致大量请求直接到达数据库,导致数据库瞬间压力骤增,设置宕机。

缓存击穿:针对某一个key(热点数据)的请求,大量并发请求都查询这一个数据,但是该数据不在缓存中,导致多请求直接访问数据库,而其他请求被阻塞等待该请求的返回结果,导致系统性能下降。

也就是说,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库

缓存穿透

当用户访问的数据,既不在缓存中,也不在数据库中,导致请求在访问缓存时,发现缓存缺失,再去访问数据库时,发现数据库中也没有要访问的数据。那么此时大量的请求都落在数据库中,导致数据库压力骤增,这就是缓存穿透问题。

b7031182f770a7a5b3c82eaf749f53b0-20230309232834574

导致原因

1. 业务误操作,缓存中的数据和数据库中的数据都被误删除了,所以导致缓存和数据库中都没有数据; 2. 黑客恶意攻击,故意大量访问某些读取不存在数据的业务; 

常见解决方法

  1. 限制非法请求

    进行参数校验,对于不合法的参数请求直接抛出异常返回给客户端。

  2. 缓存空值或者默认值

    当发现缓存穿透的现象时,可以针对查询的数据,在缓存中设置一个空值或者默认值,这样后续请求就可以从缓存中读取到空值或者默认值,返回给应用,使其不会继续查询数据库

  3. 使用布隆过滤器

    我们在写入数据库数据时,使用布隆过滤器做个标记,然后用户发起请求后,判断请求值是否存 在于布隆过滤器,如果不存在 那这个请求直接无效,如果存在 那就在缓存中查找对应的数据。
    这样当出现大量请求的时候,会先查询布隆过滤器和Redis,不会对数据库造成压力。

布隆过滤器说数据不存在,那么数据库中一定不会有这个数据。如果说数据存在,并不一定证明数据库中存在这个数据,有误判的几率,只不过几率非常小。

那么为什么会出现误判的几率呢?那就要考虑布隆过滤器的原理了

布隆过滤器由「初始值都为 0 的位图数组」和「 N 个哈希函数」两部分组成。当我们在写入数据库数据时,在布隆过滤器里做个标记,这样下次查询数据是否在数据库时,只需要查询布隆过滤器,如果查询到数据没有被标记,说明不在数据库中。

布隆过滤器会通过 3 个操作完成标记:

  • 第一步,使用 N 个哈希函数分别对数据做哈希计算,得到 N 个哈希值;
  • 第二步,将第一步得到的 N 个哈希值对位图数组的长度取模,得到每个哈希值在位图数组的对应位置。
  • 第三步,将每个哈希值在位图数组的对应位置的值设置为 1;

举个例子,假设有一个位图数组长度为 8,哈希函数 3 个的布隆过滤器。

图片

在数据库写入数据 x 后,把数据 x 标记在布隆过滤器时,数据 x 会被 3 个哈希函数分别计算出 3 个哈希值,然后在对这 3 个哈希值对 8 取模,假设取模的结果为 1、4、6,然后把位图数组的第 1、4、6 位置的值设置为 1。当应用要查询数据 x 是否数据库时,通过布隆过滤器只要查到位图数组的第 1、4、6 位置的值是否全为 1,只要有一个为 0,就认为数据 x 不在数据库中
布隆过滤器由于是基于哈希函数实现查找的,高效查找的同时存在哈希冲突的可能性,比如数据 x 和数据 y 可能都落在第 1、4、6 位置,而事实上,可能数据库中并不存在数据 y,存在误判的情况。

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!