【进阶篇】Redis缓存击穿, 穿透, 雪崩, 污染详解

【进阶篇】Redis缓存穿击, 穿透, 雪崩, 污染详解

文章目录

  • 【进阶篇】Redis缓存穿击, 穿透, 雪崩, 污染详解
  • 0. 前言
    • 大纲
    • 缓存穿击
    • 缓存穿透
    • 缓存雪崩
    • 缓存污染
  • 1. 什么是缓存穿透?
    • 1.1. 发生原因
    • 1.2. 导致问题
    • 1.3. 解决方案
  • 2. 什么是缓存击穿
    • 3.1. 发生原因
    • 3.1. 解决方案
  • 3. 什么是缓存雪崩
    • 3.1. 缓存雪崩通常发生原因
    • 3.2. 缓存雪崩的解决方案
  • 4. 什么是缓存污染
    • 4.1. 发生原因
    • 4.2. 导致问题:
    • 4.3. 缓存污染的解决方案包括:
  • 5.参考资料

在这里插入图片描述

0. 前言

背景:有个社群网友说面试的时候,在Redis 缓存环节,面试官抽风,问了他一些缓存常见问题,瞬间懵逼,关于Redis缓存穿击, 穿透, 雪崩,
污染导致的原因和预防措施,本文从网络上搜接了一些概念和解释。希望大家能吊打八股文面试官。

大纲

【进阶篇】Redis缓存击穿, 穿透, 雪崩, 污染详解_第1张图片

缓存穿击

  • 定义:攻击者针对不存在的数据不断发送请求,导致缓存层无法命中,从而对数据库层造成压力。
  • 解决方案:
    • 在缓存中设置空值占位符,避免频繁访问数据库。
    • 增加布隆过滤器,判断请求的Key是否有效。

缓存穿透

  • 定义:攻击者针对不存在的数据发送请求,绕过缓存直接访问数据库,导致数据库压力过大。
  • 解决方案:
    • 在查询结果为空时,也将结果缓存起来,设置一个较短的过期时间,避免频繁访问数据库。
    • 增加布隆过滤器,判断请求的Key是否有效。

缓存雪崩

  • 定义:缓存层的大面积失效,所有的请求都直接访问数据库,导致数据库压力过大。
  • 解决方案:
    • 设置多级缓存,避免单点故障。
    • 设置不同的缓存过期时间,避免同一时间大量缓存失效。
    • 使用限流、熔断等机制,控制访问量,避免一次性大量请求击穿缓存。

缓存污染

  • 定义:缓存中出现了异常、非法或非预期的数据,导致后续读取到的数据不正确。
  • 解决方案:
    • 增加数据校验机制,比如使用CRC校验码。
    • 限制缓存写入,只有满足一定条件(如过滤非法字符)的数据才能写入缓存。
    • 使用布隆过滤器判断数据是否有效。

1. 什么是缓存穿透?

缓存穿透是指在缓存系统中,大量的请求查询一个缓存中不存在的数据,导致这些请求都绕过了缓存层,直接查询数据库或其他存储系统。这种情况下,缓存无法提供任何帮助,而且频繁访问数据库可能会对系统的性能和稳定性产生负面影响。

1.1. 发生原因

  1. 查询一个不存在的数据:用户查询一个在数据库中不存在的数据,例如查询一个无效的用户ID或者非法的URL参数。

  2. 恶意攻击:黑客或恶意用户故意发送大量的查询请求,查询缓存中不存在的数据,以达到对系统的拒绝服务攻击。
    【进阶篇】Redis缓存击穿, 穿透, 雪崩, 污染详解_第2张图片

1.2. 导致问题

缓存穿透可能导致以下问题:

  1. 增加系统负载:缓存穿透会导致大量的请求直接访问数据库或其他存储系统,而不经过缓存,这会增加这些系统的负载,降低系统的性能和响应速度。

  2. 数据库压力增大:由于缓存穿透导致大量的请求直接访问数据库,数据库的负载会大幅增加,可能导致数据库性能下降,甚至发生数据库宕机等故障。

  3. 数据不一致:如果缓存穿透导致请求直接访问数据库,而数据库中的数据发生了变化,但缓存中的数据仍然是过期或无效的,这会导致返回的数据与实际数据不一致,可能引发业务逻辑错误或显示错误的信息。

1.3. 解决方案

  1. 空结果缓存:对于查询结果为空的情况,将空结果进行缓存,并设置一个较短的过期时间。这样再次查询相同的数据时可以直接命中缓存,避免绕过缓存直接查询数据库。

  2. 布隆过滤器:使用布隆过滤器进行预先过滤,将可能存在的数据的key进行判断,如果布隆过滤器判断某个数据的key不存在,可以直接返回空结果,避免对数据库进行查询。
    这是比较推荐的方法。所谓布隆过滤器,就是一种数据结构,它是由一个长度为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做同样操作,结果如下图:【进阶篇】Redis缓存击穿, 穿透, 雪崩, 污染详解_第3张图片

这样,当客户端查询时,也对查询的key做3次hash运算得到3个位置,然后看布隆过滤器中对应位置元素的值是否为1,如果所有对应位置元素的值都为1,就证明key在库中存在,则继续向下查询;如果3个位置中有任意一个位置的值不为1,那么就证明key在库中不存在,直接返回客户端空即可。如下图:
【进阶篇】Redis缓存击穿, 穿透, 雪崩, 污染详解_第4张图片

当客户端查询key4时,key4的3次hash运算中,有一个位置8的值为0,就说明key4在库中不存在,直接返回客户端空即可。

所以,布隆过滤器就相当于一个位于客户端与缓存层中间的拦截器一样,负责判断key是否在集合中存在。如下图:

【进阶篇】Redis缓存击穿, 穿透, 雪崩, 污染详解_第5张图片

布隆过滤器的好处就是解决了第一种缓存空值的不足,但布隆过滤器也存在缺陷,首先,它有误判的可能,比如在上面客户端查询key4的图中,假如key4经过3次hash运算得到的位置分别是2/4/6,由于这3个位置的值都是1,所以,布隆过滤器就认为key4在库中存在,进而继续向下查询了。所以,布隆过滤器判断存在的key实际上可能是不存在的,但布隆过滤器判断不存在的key是一定不存在的。它的第二个缺点就是删除元素比较难,比如现在要删除key2这个元素,那么需要将2/7/11三个位置的元素值改为0,但这样就会影响到key1和key3的判断。

  1. 缓存穿透检测:在查询数据之前,先在缓存中检查该数据是否存在,如果缓存中不存在该数据,则直接返回空结果。这样可以避免频繁查询数据库,减轻数据库的负载。

通过以上解决方案,可以有效地防止缓存穿透问题,提高系统的性能和稳定性。

2. 什么是缓存击穿

【进阶篇】Redis缓存击穿, 穿透, 雪崩, 污染详解_第6张图片
缓存击穿是指在缓存系统中,一个热点数据过期或者被删除后,恰好有大量的并发请求同时查询该数据,导致这些请求都绕过了缓存层,直接查询数据库或其他存储系统。这种情况下,缓存无法提供任何帮助,而且频繁访问数据库可能会对系统的性能和稳定性产生负面影响。

3.1. 发生原因

  1. 热点数据失效:一个热点数据在缓存中的过期时间到期或被删除,此时有大量并发请求同时查询该数

3.1. 解决方案

  1. 加锁机制:在查询缓存失效后,只允许一个请求访问数据库,其他请求等待结果。当第一个请求查询到数据后,将数据写入缓存,并释放锁,其他请求从缓存中获取数据。 【进阶篇】Redis缓存击穿, 穿透, 雪崩, 污染详解_第7张图片

  2. 异步更新缓存:在查询缓存失效后,第一个请求查询数据库,并将查询到的数据异步更新到缓存,其他请求等待缓存更新完成后再从缓存中获取数据。
    【进阶篇】Redis缓存击穿, 穿透, 雪崩, 污染详解_第8张图片

  3. 提前加载热点数据:在系统启动或者低峰期,预先加载热点数据到缓存中,避免在高峰期突然失效而引起缓存击穿。

3. 什么是缓存雪崩

缓存雪崩是指在缓存系统中,大量的缓存数据同时失效或者被删除,导致所有的请求都直接访问数据库或其他存储系统,从而造成系统的瞬时压力过大,甚至导致系统瘫痪。与缓存击穿不同的是,缓存雪崩是指大规模的缓存失效,而非单个热点数据失效。
【进阶篇】Redis缓存击穿, 穿透, 雪崩, 污染详解_第9张图片

3.1. 缓存雪崩通常发生原因

  1. 缓存过期时间设置不合理:如果缓存中大量的数据同时设置了相同的过期时间,那么当这些数据同时过期时,会导致缓存雪崩。

  2. 缓存数据集中在同一台服务器或同一片区域:如果缓存数据集中在同一台服务器或同一片区域,当该服务器或该区域发生故障或网络异常时,会导致缓存雪崩。

  3. 缓存服务器宕机或重启:如果缓存服务器宕机或重启,那么所有的缓存数据都会丢失,导致缓存雪崩。

3.2. 缓存雪崩的解决方案

  1. 设置合理的缓存过期时间:合理地设置缓存数据的过期时间,避免大量的数据同时过期。

  2. 分散缓存失效时间:将缓存数据的过期时间随机分布,避免大量数据同时过期。

  3. 使用多级缓存:在系统架构中引入多级缓存,将缓存数据分散到不同的缓存服务器或缓存区域,减少单一故障点。

  4. 引入热点数据预热:在系统启动或者低峰期,预先加载热点数据到缓存中,避免在高峰期突然失效而引起缓存雪崩。

4. 什么是缓存污染

缓存污染是指在缓存系统中,由于错误的缓存配置或缓存数据异常,导致缓存中存储了无效或错误的数据,进而影响系统的正常运行。

4.1. 发生原因

  1. 缓存键冲突:不同的数据存储在缓存中使用了相同的缓存键,导致缓存数据被覆盖或混淆。这可能是由于不同的数据模块使用了相同的缓存键,或者在缓存键生成逻辑中存在错误。

  2. 缓存数据异常:缓存数据在存储或读取过程中出现异常,例如数据格式错误、数据丢失、数据损坏等。如果这些异常数据被存储到缓存中,将导致后续的请求获取到错误的数据。

  3. 缓存穿透:由于恶意攻击或异常情况,大量的请求访问缓存系统中不存在的数据,导致这些请求直接访问数据库或其他存储系统,而不是从缓存中获取数据。

4.2. 导致问题:

  1. 返回错误的数据:当缓存中存储了错误的数据时,后续的请求获取到的数据将是错误的,可能导致系统的功能异常或显示错误的信息。

  2. 增加系统负载:如果大量的请求绕过缓存直接访问数据库或其他存储系统,将会增加这些系统的负载,降低系统的性能和响应速度。

4.3. 缓存污染的解决方案包括:

  1. 缓存键设计合理:确保不同的数据模块使用不同的缓存键,避免缓存键冲突。

  2. 数据校验和容错处理:在缓存数据存储和读取过程中,进行数据校验,确保数据的完整性和准确性。对于异常数据,可以进行容错处理,例如删除或重新获取正确的数据。

  3. 缓存穿透防护:使用布隆过滤器等技术,对于不存在的数据进行预判,避免无效请求直接访问存储系统。

5.参考资料

  1. Redis官方文档:https://redis.io/
  2. Redis实战(书籍)
  3. Redis设计与实现(书籍)
  4. https://www.toutiao.com/article/7088132873051488780/

你可能感兴趣的:(缓存,redis,缓存击穿,缓存穿透,缓存雪崩,缓存污染)