什么是缓存穿透、缓存击穿、缓存雪崩,以及各自的解决方案

什么是缓存穿透、缓存击穿、缓存雪崩

缓存雪崩

当缓存数据大面积失效,导致请求无法从缓存中拿到数据而是直接访问数据库。
在这里插入图片描述

缓存穿透

缓存穿透是指查询一个缓存中和数据库中都不存在的数据,导致每次查询这条数据都会透过缓存,直接查库,最后返回空。当用户使用这条不存在的数据疯狂发起查询请求的时候,对数据库造成的压力就非常大,甚至可能直接挂掉。这种情况的流程就变成下图这样了:
在这里插入图片描述

缓存击穿

缓存击穿是指当缓存中某个热点数据过期了,在该热点数据重新载入缓存之前,有大量的查询请求穿过缓存,直接查询数据库。这种情况会导致数据库压力瞬间骤增,造成大量请求阻塞,甚至直接挂掉。
在这里插入图片描述

解决方案

缓存雪崩

针对第一种大量key同时过期的情况,解决起来比较简单,只需要将每个key的过期时间打散即可,使它们的失效点尽可能均匀分布。

针对第二种redis发生故障的情况,部署redis时可以使用redis的几种高可用方案部署,部署方法可以参考我之前的文章Redis高可用方案—主从(masterslave)架构、Redis高可用架构—哨兵(sentinel)机制详细介绍、Redis高可用架构—Redis集群(Redis Cluster)详细介绍。

除了上面两种解决方式,还可以使用其他策略,比如设置key永不过期、加分布式锁等。

缓存穿透

解决缓存穿透的方法一般有两种,第一种是缓存空对象,第二种是使用布隆过滤器。

第一种方法比较好理解,就是当数据库中查不到数据的时候,我缓存一个空对象,然后给这个空对象的缓存设置一个过期时间,这样下次再查询该数据的时候,就可以直接从缓存中拿到,从而达到了减小数据库压力的目的。但这种解决方式有两个缺点:(1)需要缓存层提供更多的内存空间来缓存这些空对象,当这种空对象很多的时候,就会浪费更多的内存;
(2)会导致缓存层和存储层的数据不一致,即使在缓存空对象时给它设置了一个很短的过期时间,那也会导致这一段时间内的数据不一致问题。

第二种方案是使用布隆过滤器,这是比较推荐的方法。所谓布隆过滤器,就是一种数据结构,它是由一个长度为m bit的位数组与n个hash函数组成的数据结构,位数组中每个元素的初始值都是0。在初始化布隆过滤器时,会先将所有key进行n次hash运算,这样就可以得到n个位置,然后将这n个位置上的元素改为1。这样,就相当于把所有的key保存到了布隆过滤器中了。

举个例子,比如我们一共有3个key,我们对这3个key分别进行3次hash运算,key1经过三次hash运算后的结果分别为2/6/10,那么就把布隆过滤器中下标为2/6/10的元素值更新为1,然后再分别对key2和key3做同样操作,

当客户端查询时,也对查询的key做3次hash运算得到3个位置,然后看布隆过滤器中对应位置元素的值是否为1,如果所有对应位置元素的值都为1,就证明key在库中存在,则继续向下查询;如果3个位置中有任意一个位置的值不为1,那么就证明key在库中不存在,直接返回客户端空即可

缓存击穿

解决缓存击穿的方法也有二种,第一种是设置key永不过期;第二种是使用分布式锁,保证同一时刻只能有一个查询请求重新加载热点数据到缓存中,这样,其他的线程只需等待该线程运行完毕,即可重新从Redis中获取数据。

1、在设置热点key的时候,不给key设置过期时间即可。不过还有另外一种方式也可以达到key不过期的目的,就是正常给key设置过期时间,不过在后台同时启一个定时任务去定时地更新这个缓存。

2、使用加锁的方式,锁的对象就是key,这样,当大量查询同一个key的请求并发进来时,只能有一个请求获取到锁,然后获取到锁的线程查询数据库,然后将结果放入到缓存中,然后释放锁,此时,其他处于锁等待的请求即可继续执行,由于此时缓存中已经有了数据,所以直接从缓存中获取到数据返回,并不会查询数据库。

相关推荐

  1. 缓存穿透击穿雪崩解决方法

    2023-12-11 11:08:04       8 阅读
  2. 什么缓存击穿缓存穿透缓存雪崩

    2023-12-11 11:08:04       16 阅读
  3. Redis缓存穿透缓存雪崩缓存击穿解决方案

    2023-12-11 11:08:04       10 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-11 11:08:04       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-11 11:08:04       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-11 11:08:04       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-11 11:08:04       18 阅读

热门阅读

  1. 线程组、线程切换、线程异常

    2023-12-11 11:08:04       44 阅读
  2. scheduleatfixedrate详解

    2023-12-11 11:08:04       39 阅读
  3. Presto集群安装部署

    2023-12-11 11:08:04       44 阅读
  4. springboot自定义cron定时任务执行

    2023-12-11 11:08:04       37 阅读
  5. 第三十一章 控制到 XML 模式的映射 - %ListOfDataTypes

    2023-12-11 11:08:04       23 阅读
  6. SAP ABAP 对象ALV的一些功能(ALV资料五)

    2023-12-11 11:08:04       29 阅读
  7. # C语言——预处理(#define,#if..)

    2023-12-11 11:08:04       28 阅读
  8. TS条件类型、断言及名义类型

    2023-12-11 11:08:04       36 阅读
  9. Electron[5] 渲染进程和主进程

    2023-12-11 11:08:04       42 阅读
  10. 【打卡】牛客网:BM61 矩阵最长递增路径

    2023-12-11 11:08:04       35 阅读