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

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
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
相关文章
|
2天前
|
存储 缓存 NoSQL
解决Redis缓存数据类型丢失问题
解决Redis缓存数据类型丢失问题
111 85
|
1月前
|
缓存 NoSQL 关系型数据库
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
本文详解缓存雪崩、缓存穿透、缓存并发及缓存预热等问题,提供高可用解决方案,帮助你在大厂面试和实际工作中应对这些常见并发场景。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
|
1月前
|
存储 缓存 NoSQL
【赵渝强老师】基于Redis的旁路缓存架构
本文介绍了引入缓存后的系统架构,通过缓存可以提升访问性能、降低网络拥堵、减轻服务负载和增强可扩展性。文中提供了相关图片和视频讲解,并讨论了数据库读写分离、分库分表等方法来减轻数据库压力。同时,文章也指出了缓存可能带来的复杂度增加、成本提高和数据一致性问题。
【赵渝强老师】基于Redis的旁路缓存架构
|
23天前
|
缓存 NoSQL 数据库
缓存穿透、缓存击穿和缓存雪崩及其解决方案
在现代应用中,缓存是提升性能的关键技术之一。然而,缓存系统也可能遇到一系列问题,如缓存穿透、缓存击穿和缓存雪崩。这些问题可能导致数据库压力过大,甚至系统崩溃。本文将探讨这些问题及其解决方案。
|
1月前
|
缓存 NoSQL Redis
Redis 缓存使用的实践
《Redis缓存最佳实践指南》涵盖缓存更新策略、缓存击穿防护、大key处理和性能优化。包括Cache Aside Pattern、Write Through、分布式锁、大key拆分和批量操作等技术,帮助你在项目中高效使用Redis缓存。
248 22
|
1月前
|
缓存 NoSQL PHP
Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出
本文深入探讨了Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出。文章还介绍了Redis在页面缓存、数据缓存和会话缓存等应用场景中的使用,并强调了缓存数据一致性、过期时间设置、容量控制和安全问题的重要性。
40 5
|
1月前
|
缓存 NoSQL 中间件
redis高并发缓存中间件总结!
本文档详细介绍了高并发缓存中间件Redis的原理、高级操作及其在电商架构中的应用。通过阿里云的角度,分析了Redis与架构的关系,并展示了无Redis和使用Redis缓存的架构图。文档还涵盖了Redis的基本特性、应用场景、安装部署步骤、配置文件详解、启动和关闭方法、systemctl管理脚本的生成以及日志警告处理等内容。适合初学者和有一定经验的技术人员参考学习。
194 7
|
存储 缓存 NoSQL
Spring Boot2.5 实战 MongoDB 与高并发 Redis 缓存|学习笔记
快速学习 Spring Boot2.5 实战 MongoDB 与高并发 Redis 缓存
Spring Boot2.5 实战 MongoDB 与高并发 Redis 缓存|学习笔记
|
缓存 NoSQL 安全
6.0Spring Boot 2.0实战 Redis 分布式缓存6.0|学习笔记
快速学习6.0Spring Boot 2.0实战 Redis 分布式缓存6.0。
337 0
6.0Spring Boot 2.0实战 Redis 分布式缓存6.0|学习笔记
|
缓存 NoSQL Redis
首页数据显示-添加 redis 缓存(3)| 学习笔记
快速学习 首页数据显示-添加 redis 缓存(3)
154 0
首页数据显示-添加 redis 缓存(3)| 学习笔记
下一篇
DataWorks