redis之缓存穿透,击透,雪崩~

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: redis之缓存穿透,击透,雪崩~

以下为一个我们正常的缓存流程:

缓存雪崩:

在双十一的时候,淘宝的首页访问量是非常大的,所以它的很多数据是放在redis缓存里面,对应redis中的key,假设设置了缓存失效的时间为3小时,超过这三个小时后,在一瞬间redis缓存key大量失效,导致所有的请求都要直接和数据库交互,就会导致数据库响应不及时挂掉,此时首页就没办法向外界提供服务了,这就是缓存雪崩。

缓存雪崩解决方案:

1:设置缓存的失效时间,在初始化的时候,我们可以随机初始化它的失效时间,不要让他们都在同一时间失效


2:设置过期标志更新缓存,记录缓存数据是否过期(设置提前量),如果过期会触发通知另外的线程在后台去更新实际key的缓存。


3:构建多级缓存架构:nginx缓存+redis缓存+其他缓存等

缓存穿透:

缓存穿透解决方案:

1:如果这个请求穿透redis直接到数据库,那么数据库无论查询到什么样的结果,都将结果缓存到redis中去,那么等下次,它使用同样的恶意数据,就不会穿透redis,但如果这个老六换了不同的参数,该解决办法就失效了


2:将这个老六的ip拉黑,但这个老六也可能换不同的ip


3:对参数的合法性检验,在判断这个参数不合法的时候就直接return


4:使用布隆过滤器(推荐!),下文有讲述

缓存击穿:

商品的秒杀,在秒杀之前程序员会将该商品的数据放到redis缓存中,对应redis中的一个key,假设设置key的过期时间为4个小时,但直到4个半小时,秒杀依然没有结束,而此时该商品的key缓存突然失效了,导致大量的请求在redis缓存中查询不到数据,那么就会直接访问数据库,从而导致数据库响应不及时而挂掉,该过程就叫缓存击穿

缓存击穿解决方案:

1:预先设置热门数据:在redis高峰访问之前,把一些热门的数据提前存入到redis里面,加大这些热门数据key的时长。

2:实时调整:现场监控那些数据热门,实时调整key的过期时间。

3:让数据对应的key永远不过期

4:使用分布式锁,单体应用使用互斥锁

布隆过滤器:

它其实就是一个很长的二进制向量,如下所示:

布隆过滤器的作用就是判断一个数据存不存在这个数组里面,如果不存在就是0,存在就是1

它是由一串二进制数组组成的数据,所以它占据的空间是非常小的,它插入和查询的操作是非常快的,因为它是计算这个数据的哈希值,再由哈希值映射到这个数组的下标,只需要根据算好的下标找对应的值即可,所以它的时间复杂度为O(K),之所以是O(K)不是O(1),是因为哈希函数的个数是不确定的,并且由于过滤器本身的数据就是二进制只有数字0和1,不存储原始数据,那么就使得保密性非常好。


但它也存在着许多的缺点,如下所示,布隆过滤器很难完成删除工作


假设有两个数据,“你好”和“hello”,经过哈希值运算,最终都被存储在下标为2的位置,那么我们仅根据下标就无法判断到底存储的是那个数据

假设此时我们要删除“hello”这个数据,经过一系列运算,算出它在下标为2的这个位置,那么将下标2位置的这个1改成0,就代表已经删除这个数据了,但是由于“你好”这个数据也存储在这里啊,所以删除“hello”的同时把“你好”也删除了,就会造成数据的误删。


此外,它还有一个最大的缺点,它很容易进行误判,因为不同数据计算出来的哈希值可能是相同的,所以存在相同的哈希值,就会存在误判的情况,如下所示:


假设当前下标位2的位置只存储了数据“你好”,此时数据“hello”经过计算也需要存储在下标为2的位置,但判断过后,发现这里已经有数据了,那么就会误判数据“hello”已经存在了

而上述的这种误判几乎是解决不了的问题,只能减少误判的概率,那么我们怎么去减少误判的概率呢?

如下所示,我们使用Java实现布隆过滤器,我这里使用的是guava是由谷歌公司提供的工具包,里面提供了布隆过滤器的实现。

第一步:导入对应的依赖

 <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>30.1.1-jre</version>
 </dependency>

第二步:编写测试类:

package org.example;
import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
import java.nio.charset.StandardCharsets;
public class bulong {
    public static void main(String[] args) {
        // 初始化布隆过滤器,设计预计元素数量为1000000L,误差率为3%
        BloomFilter<CharSequence> bloomFilter = BloomFilter.create(Funnels.stringFunnel(StandardCharsets.UTF8), 100_0000, 0.03);
        int n = 1000000;
        for (int i = 0; i < n; i++) {
            bloomFilter.put(String.valueOf(i));
        }
        int count = 0;
        for (int i = 0; i < (n * 2); i++) {
            if (bloomFilter.mightContain(String.valueOf(i))) {
                count++;
            }
        }
        System.out.println("过滤器误判率:" + 1.0 * (count - n) / n);
    }
}

将误判率设置为0.01

 BloomFilter<CharSequence> bloomFilter = BloomFilter.create(Funnels.stringFunnel(StandardCharsets.UTF_8), 1000000, 0.01);

输出如下所示:

我们所设置的误判率是能影响最终的误判结果的,误判率设置的越低,计算所需的时间会越久,所需要的空间量就越大,所需的哈希函数就越多,原因对同一个数据使用多个不同的哈希函数所得到的哈希值相同的概率就越低,那么它们不同的数据存储在相同的位置的概率就越低,误判的概率就越低,但是由于哈希函数增多了,就会导致计算出的哈希值增多,进而导致二进制数据增多,所以也会占用更多的空间。

布隆过滤器解决缓存穿透问题:

我们可以将布隆过滤器理解为一个黑名单或者白名单,因为它的主要作用就是判断这个元素存不存在这个白名单或者黑名单里面,

布隆过滤器白名单:

布隆过滤器黑名单:

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
8天前
|
缓存 NoSQL Redis
Redis 缓存使用的实践
《Redis缓存最佳实践指南》涵盖缓存更新策略、缓存击穿防护、大key处理和性能优化。包括Cache Aside Pattern、Write Through、分布式锁、大key拆分和批量操作等技术,帮助你在项目中高效使用Redis缓存。
66 22
|
7天前
|
缓存 NoSQL 中间件
redis高并发缓存中间件总结!
本文档详细介绍了高并发缓存中间件Redis的原理、高级操作及其在电商架构中的应用。通过阿里云的角度,分析了Redis与架构的关系,并展示了无Redis和使用Redis缓存的架构图。文档还涵盖了Redis的基本特性、应用场景、安装部署步骤、配置文件详解、启动和关闭方法、systemctl管理脚本的生成以及日志警告处理等内容。适合初学者和有一定经验的技术人员参考学习。
65 7
|
12天前
|
存储 缓存 监控
利用 Redis 缓存特性避免缓存穿透的策略与方法
【10月更文挑战第23天】通过以上对利用 Redis 缓存特性避免缓存穿透的详细阐述,我们对这一策略有了更深入的理解。在实际应用中,我们需要根据具体情况灵活运用这些方法,并结合其他技术手段,共同保障系统的稳定和高效运行。同时,要不断关注 Redis 缓存特性的发展和变化,及时调整策略,以应对不断出现的新挑战。
44 10
|
12天前
|
缓存 监控 NoSQL
Redis 缓存穿透的检测方法与分析
【10月更文挑战第23天】通过以上对 Redis 缓存穿透检测方法的深入探讨,我们对如何及时发现和处理这一问题有了更全面的认识。在实际应用中,我们需要综合运用多种检测手段,并结合业务场景和实际情况进行分析,以确保能够准确、及时地检测到缓存穿透现象,并采取有效的措施加以解决。同时,要不断优化和改进检测方法,提高检测的准确性和效率,为系统的稳定运行提供有力保障。
42 5
|
12天前
|
缓存 监控 NoSQL
Redis 缓存穿透及其应对策略
【10月更文挑战第23天】通过以上对 Redis 缓存穿透的详细阐述,我们对这一问题有了更深入的理解。在实际应用中,我们需要根据具体情况综合运用多种方法来解决缓存穿透问题,以保障系统的稳定运行和高效性能。同时,要不断关注技术的发展和变化,及时调整策略,以应对不断出现的新挑战。
34 4
|
1月前
|
存储 缓存 NoSQL
数据的存储--Redis缓存存储(一)
数据的存储--Redis缓存存储(一)
|
1月前
|
存储 缓存 NoSQL
数据的存储--Redis缓存存储(二)
数据的存储--Redis缓存存储(二)
数据的存储--Redis缓存存储(二)
|
1月前
|
消息中间件 缓存 NoSQL
Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。
【10月更文挑战第4天】Redis 是一个高性能的键值对存储系统,常用于缓存、消息队列和会话管理等场景。随着数据增长,有时需要将 Redis 数据导出以进行分析、备份或迁移。本文详细介绍几种导出方法:1)使用 Redis 命令与重定向;2)利用 Redis 的 RDB 和 AOF 持久化功能;3)借助第三方工具如 `redis-dump`。每种方法均附有示例代码,帮助你轻松完成数据导出任务。无论数据量大小,总有一款适合你。
68 6
|
1月前
|
缓存 NoSQL 关系型数据库
redis和缓存及相关问题和解决办法 什么是缓存预热、缓存穿透、缓存雪崩、缓存击穿
本文深入探讨了Redis缓存的相关知识,包括缓存的概念、使用场景、可能出现的问题(缓存预热、缓存穿透、缓存雪崩、缓存击穿)及其解决方案。
159 0
redis和缓存及相关问题和解决办法 什么是缓存预热、缓存穿透、缓存雪崩、缓存击穿
|
13天前
|
缓存 NoSQL Java
有Redis为什么还要本地缓存?谈谈你对本地缓存的理解?
有Redis为什么还要本地缓存?谈谈你对本地缓存的理解?
37 0
有Redis为什么还要本地缓存?谈谈你对本地缓存的理解?
下一篇
无影云桌面