让你弄懂什么是缓存穿透,并轻松get布隆过滤器原理,快速上手。

本文介绍缓存穿透现象及其解决方案,并深入探讨布隆过滤器的工作原理及其实现方式,包括Guava和Redis的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、什么是缓存穿透?

一图胜千言,如下图,当访问到数据库中没有的数据的时候,每次访问同样的数据,都会绕过缓存系统(一般是Redis),直接访问到数据库层,这就是我们说的缓存穿透。

解决办法:

我们可以在缓存中将这样的数据也缓存起来,只是缓存的key的value为空。

但是如果有特别多的key是这种情况的,我们的缓存中要缓存好多这样的key,比较占用缓存。

另外如果这种key访问的次数比较少,我们缓存这种key的效果也不是很好。

于是引出了一种办法:

我们有什么办法可以让这样的数据在访问缓存之前,就可以被判断出来是否在我们的系统中呢?

对,这就是布隆过滤器要做的事情了。他可以判断一个key是否存在。
在这里插入图片描述

二、布隆过滤器原理

布隆过滤器是位图的数据结构,与一系列哈希算法的结合。

我们有四个key:key1、key2、key3、key4。

两种哈希算法:hash1、hash2。

我们将每个key用多种哈希算法映射到我们下面的位图中。

当我们判断一个key是否存在的时候,就去对应的位置上看值是否都为1。

但是有一个问题,如果key对应的位置不都为1,那么这个key一定不存在。

但是key对应位置都为1,这个key不一定存在于我们的系统当中,有些晕了吧,看下图的key3不一定存在与我们系统中哦,因为他对应的位置上可能是其他的key对应的。

也就是说布隆过滤器是有误差的
在这里插入图片描述

三、上手布隆过滤器

我知道了布隆过滤器的原理,那么如何来使用呢?

难道这些算法要我们自己来实现吗?当然不用啦。

1、guava的实现

guava里面已经有实现了,我们直接引入jar包后,直接调用就好了。

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>19.0</version>
</dependency>

代码如下:

// 预计要插入多少数据
private static int size = 1000000;

// 期望的误判率
private static double fpp = 0.01;

private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), size, fpp);

public static void main(String[] args) {
    // 插入数据
    for (int i = 0; i < 1000000; i++) {
        bloomFilter.put(i);
    }
    int count = 0;
    for (int i = 1000000; i < 2000000; i++) {
        if (bloomFilter.mightContain(i)) {
            count++;
        }
    }
    System.out.println("总共的误判数: " + count);
}

2、Redis的实现

我们去RedisBloom的官网下载源文件。

然后呢,将下载的jar包make一下。

Redis会以module的方式将RedisBloom加载进来使用,类似于扩展的效果。

我们只需要在Redis的配置文件redis.conf中加入编译完的RedisBloom生成的可执行命令的路径,即可,如下:

loadmodule /root/RedisBloom-2.2.4/redisbloom.so

在我们的命令行中,就可以使用如下命令操作布隆过滤器了:

-- 向我们的布隆过滤器当中加入要判断的内容
bf.add 
-- 判断内容是否存在于我们的布隆过滤器当中
bf.exists
-- 初始化我们的布隆过滤器,如打算里面放入多少个元素,能容忍的误差率
bf.reserve

根据我们的预期,布隆过滤器底层会来判断使用多少位的位图,使用几个hash算法等,实现我们的目标。

四、总结时间

布隆过滤器利用较小的空间,应用于判断大量key是否存在的场景。

guava的实现,利用应用程序所在服务器的内存资源,多个服务器的话,需要自己判断自己的。

Redis的实现,利用Redis的内存资源,应用程序可以调用Redis中的布隆过滤器来做相应判断。

本文从缓存穿透的问题,到如何解决缓存穿透的问题,再到布隆过滤器的原理,以及如何应用布隆过滤器,和对比其实现方式,期望能够对大家有所帮助。

<think>嗯,用户之前让我介绍过如何快速掌握MyBatis-Plus,现在又来问Redis,看来他们可能是在学习后端开发相关的技术栈。需要确保这次回答的结构和之前类似,保持一致性,这样用户更容易理解和对比。 首先,得确定用户对Redis的了解程度。可能他们已经有数据库的基本知识,但需要快速上手Redis的应用场景和基础操作。用户可能希望了解Redis的核心概念、安装配置、基本命令以及如何在实际项目中应用。 需要分步骤来介绍,像之前MyBatis-Plus那样,分核心定位、安装配置、基础操作、进阶功能、应用场景、注意事项和学习资源。每个部分要简明扼要,突出关键点,避免信息过载。 考虑到用户可能是在Spring Boot环境中使用,应该包括如何在Spring Boot中整合Redis的示例,比如配置和模板使用。同时,要提醒常见的坑,比如持久化配置、内存管理和集群方案,这些是实际开发中容易遇到的问题。 还要注意用户之前提到的格式要求,比如数学公式和代码块的使用。虽然Redis的介绍可能涉及较少的数学公式,但代码示例需要正确使用格式,比如Java配置和Redis命令的示例。 需要检查是否有遗漏的重要功能,比如事务、Lua脚本、发布订阅等,但作为快速掌握,可能先集中在基础部分,高级功能可以简要提及或引导到官方文档。 最后,确保语言简洁,结构清晰,重点突出,帮助用户快速上手,同时提供进一步学习的资源,如官方文档和推荐书籍,满足不同层次的需求。</think>以下是一份快速掌握Redis的实用指南,分层讲解核心知识点与实战技巧: --- ### 一、Redis核心定位 是**内存型键值数据库**(NoSQL),支持持久化,特点: - 高性能:$10^5$次/秒读写(单机) - 数据结构丰富:String/Hash/List/Set/ZSet等 - 应用场景:缓存、计数器、消息队列、分布式锁等 --- ### 二、快速安装与配置(Linux环境) #### 1. 安装Redis ```bash wget https://download.redis.io/releases/redis-7.0.12.tar.gz tar xzf redis-7.0.12.tar.gz cd redis-7.0.12 && make ``` #### 2. 启动服务 ```bash src/redis-server redis.conf # 默认端口6379 ``` #### 3. 客户端连接 ```bash src/redis-cli > PING # 返回PONG表示连接成功 ``` --- ### 三、5大核心数据结构操作 #### 1. String(字符串) ```redis SET user:1 "Alice" # 存储 GET user:1 # 获取 INCR counter # 自增计数器 ``` #### 2. Hash(哈希表) ```redis HSET product:1001 name "Phone" price 2999 HGET product:1001 price ``` #### 3. List(双向链表) ```redis LPUSH news:latest "头条A" # 左侧插入 LRANGE news:latest 0 5 # 获取前6条 ``` #### 4. Set(无序集合) ```redis SADD tags:article:1 "科技" "编程" SINTER tags:article:1 tags:article:2 # 求交集 ``` #### 5. ZSet(有序集合) ```redis ZADD leaderboard 95 "PlayerA" ZREVRANGE leaderboard 0 9 WITHSCORES # 排行榜TOP10 ``` --- ### 四、进阶实战技巧 #### 1. 过期策略 ```redis SET session:xyz "data" EX 3600 # 自动1小时后过期 TTL session:xyz # 查看剩余生存时间 ``` #### 2. 管道(Pipeline) ```bash echo -e "SET key1 val1\nGET key1" | redis-cli --pipe # 批量执行减少网络开销 ``` #### 3. Lua脚本原子操作 ```lua -- 实现分布式锁 if redis.call("GET", KEYS[1]) == ARGV[1] then return redis.call("DEL", KEYS[1]) end return 0 ``` --- ### 五、Spring Boot整合示例 #### 1. 添加依赖 ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` #### 2. 配置连接 ```yaml spring: redis: host: 127.0.0.1 port: 6379 database: 0 ``` #### 3. 使用RedisTemplate ```java @Autowired private RedisTemplate<String, Object> redisTemplate; public void setValue(String key, Object value) { redisTemplate.opsForValue().set(key, value, 30, TimeUnit.MINUTES); } ``` --- ### 六、避坑指南 1. **内存溢出**:监控`used_memory`,设置`maxmemory`和淘汰策略(volatile-lru/allkeys-lru) 2. **缓存穿透**:使用布隆过滤器缓存空值 3. **缓存雪崩**:设置随机过期时间,集群部署 4. **持久化选择**: - RDB(快照):适合备份,可能丢失数据 - AOF(日志):更高数据安全性,性能较低 --- ### 七、学习路线建议 1. 掌握基础命令 → 2. 理解持久化机制 → 3. 学习集群方案 → 4. 研究应用场景 **官方资源**: - 命令手册:[redis.io/commands](https://redis.io/commands/) - 中文文档:[redis.com.cn](http://www.redis.com.cn/) - 推荐书籍:《Redis设计与实现》《Redis开发与运维》
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值