首页 >数据库 >Redis > 正文

一文搞懂redis缓存雪崩、缓存击穿和缓存穿透

转载2022-11-14 20:29:091085 + php学习QQ群(点击入群)
本篇文章给大家带来了关于Redis的相关知识,其中主要介绍了关于缓存雪崩、缓存击穿和缓存穿透的相关内容,下面一起来看一下,希望对大家有帮助。

千万级数据并发如何处理?进入学习

推荐学习:Redis视频教程

关于Redis的高频问题,缓存雪崩、缓存击穿和缓存穿透一定少不了,相信大家在面试中都被问到过类似的问题。为什么这些问题一直热门呢?因为我们在使用Redis缓存时,这些问题都是很容易遇到的。接下来我们就来看看这些问题都是怎么产生的,对应的解决方案都有哪些吧。

缓存雪崩

首先来看看缓存雪崩,缓存雪崩的概念就是:大量的请求没有在Redis缓存中得到处理,从而导致请求都涌入到数据库中,然后数据库的压力剧增。

引起缓存雪崩的原因可总结为2个:

  • 缓存中有大量的数据同时过期,这样此时大量的请求都怼到数据库了。
  • Redis缓存实例发生故障了,无法处理大量请求,也会导致请求都跑到数据库去了。

先来看看第一个场景:缓存中大量的数据同时过期问题。

缓存中大量的数据同时过期

结合图例来看,就是大量的数据在同一时间过期,然后此时又有很多的请求要读取这些数据。当然就会发生缓存雪崩,从而导致数据库压力剧增了。

大量数据同时过期的解决方案

应对大量数据同时过期问题,通常有2种方案:

  • 数据过期设置增加随机时间:也就是用expire命令给数据设置过期时间时,增加一个随机的时间,比如数据a是5分钟过期,在5分钟的基础上随机增加10-120秒时间。这样就能避免大量数据同时过期。
  • 服务降级:也就是发生缓存雪崩时,(1)若访问的不是核心数据,当没有缓存命中时,不去数据库了,直接返回预先设置好的信息,比如空值或者错误信息;(2)当访问的是核心数据,缓存未命中时,允许去数据库查询。这样就将不是核心数据的请求都拒绝怼到数据库了。

看完了大量数据同时过期的情况,再来看看Redis缓存实例故障的情况。

Redis缓存实例故障导致的缓存雪崩

这种情况下,Redis无法处理读请求了,请求自然就怼到数据库了。

通常来说,应对这种情况,我们也有2种方式:

  • 在业务系统中做好服务熔断/请求限流
  • 事前预防:构建Redis高可靠集群,比如主从集群的主备切换。

服务熔断,也就是当Redis发生故障时,暂停请求对缓存系统的访问。等到Redis恢复正常了再打开请求访问。

这种方式我们需要对Redis或数据库的运行状态进行监控,比如MySQL的负载压力、Redis的CPU使用率、内存使用率及QPS等。当发现Redis实例缓存雪崩了,就暂停服务。

这种情况能有效放置大量请求对数据库造成压力。但是会暂停请求访问,对业务端的影响很大。

因此,为了减少对业务端的影响,我们可以使用请求限流方式,控制QPS,避免过多的请求怼到数据库去。比如下面图例,本身有2万每秒的请求,但因为Redis故障宕机了。我们限流操作将qps降到2千每秒,数据库处理2000的qps还是没问题的。

缓存击穿

缓存击穿就是指个别访问频繁的热点数据无法缓存命中,然后请求都涌入到数据库中。它经常会在热点数据过期时发生。

对于缓存击穿问题,我们知道这些都是被访问非常频繁的热点数据,处理方式就简单粗暴了,直接不设置过期时间了。等热点数据不频繁访问再手动处理即可。

缓存穿透

缓存雪崩有些特别,它是指要访问的数据既不在Redis缓存,也不在数据库中。当大量请求进到系统时,Redis和数据库都会有巨大压力。

导致缓存穿透的原因通常有2种:

  • 数据被误删除了,导致缓存和数据库都没有数据了。然而客户端是不知道的,还在疯狂请求。
  • 有恶意攻击的情况:也就是被人盯上了,专门去查没有的数据。

对于缓存穿透的情况,解决方案可以参考下面几种:

  • 是对缓存设置空值或者默认值。 比如发生缓存穿透时,在Redis缓存中设置空值/默认值。后续查询该值时就直接返回这个默认值了。
  • 使用布隆过滤器来判断数据是否存在,避免从数据库查询。
  • 在前端就进行请求检测。 比如在前端将一些不合法的请求直接过滤,不要发到后端来处理。

第一点和第三点比较容易理解,这里就不展开描述。我们重点来看看第二点:布隆过滤器。

布隆过滤器

布隆过滤器主要用于判断一个元素是否在一个集合中。它是由一个固定大小的二进制向量(可理解成默认为0的bit数组)和一系列的映射函数组成的。

我们首先来看看布隆过滤器是如何标记一个数据a的:

  • 第一步,会使用到多个映射函数(哈希函数),每个函数都会计算这个数据a的哈希值;
  • 第二步,这些计算得出的哈希值会分别对bit数组长度取模,这样就得到每个哈希值在数组上的位置;
  • 第三步,把第二步得到的位置,分别在bit数组上设置为1。

通过这3个步骤,数据标记就完成了。然后要查询数据在不在的时候是这样做的:

  • 先计算这个数据在bit数组中的多个位置;
  • 然后分别查看bit数组的这些位置的bit值。只有每个位置的bit值都为1,说明数据才可能存在,否则数据一定不存在。

结合下图来看,基本原理就是这样。

image.png

推荐学习:Redis视频教程

以上就是一文搞懂redis缓存雪崩、缓存击穿和缓存穿透的详细内容,更多请关注php中文网其它相关文章!

声明:本文转载于:掘金,如有侵犯,请联系admin@php.cn删除

  • 相关标签:redis
  • 程序员必备接口测试调试工具:点击使用

    Apipost = Postman + Swagger + Mock + Jmeter

    Api设计、调试、文档、自动化测试工具

    网页生成APP,用做网站的技术去做APP:立即创建

    手机网站开发APP、自助封装APP、200+原生模块、2000+映射JS接口按需打包

    相关文章

    相关视频


    视频教程分类

    专题推荐

    官方公众号

    php中文网课程

    扫码关注官方公众号
    回复“phpcn01”领取php学习资料课程
    全套工具、电子书、脑图、内部课程等

    推荐视频教程

    开通VIP会员课 0元学

    热门推荐