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

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

1. Redis + 布隆过滤器解决缓存穿透问题

📌 什么是缓存穿透?

缓存穿透指的是查询的数据既不在缓存,也不在数据库,导致每次查询都直接访问数据库,增加数据库压力。
例如:攻击者故意请求不存在的 ID,导致大量无效查询,冲垮数据库。

解决方案

  • 普通缓存机制:数据库查询为空时,写入一个短期过期的空值,但对高并发请求不够高效。

  • 布隆过滤器方案

    (推荐):

    1. 布隆过滤器预存已有数据的 key
    2. 查询前,先通过布隆过滤器判断 key 是否可能存在:
      • 存在 → 查询 Redis 缓存,未命中则查询数据库,再写入缓存。
      • 不存在 → 直接返回,避免访问数据库,防止缓存穿透。

2. Java 代码示例:Redis + 布隆过滤器

📌 依赖

使用 Redisson 库来操作 Redis 的布隆过滤器,需要添加以下依赖(使用 MavenGradle)。

<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.21.1</version>
</dependency>

📌 代码示例

🚀 1. 初始化 Redis 连接
import org.redisson.Redisson;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;public class RedisBloomFilter {private static RedissonClient redissonClient;private static RBloomFilter<String> bloomFilter;static {// 配置 Redis 连接Config config = new Config();config.useSingleServer().setAddress("redis://127.0.0.1:6379"); // 连接本地 RedisredissonClient = Redisson.create(config);// 初始化布隆过滤器bloomFilter = redissonClient.getBloomFilter("product_bloom_filter");bloomFilter.tryInit(1000000L, 0.01); // 预估 100w 个元素,误判率 1%}/*** 向布隆过滤器添加数据*/public static void addToBloomFilter(String productId) {bloomFilter.add(productId);}/*** 判断数据是否可能存在*/public static boolean mightContain(String productId) {return bloomFilter.contains(productId);}public static void main(String[] args) {// 模拟初始化布隆过滤器addToBloomFilter("1001");addToBloomFilter("1002");addToBloomFilter("1003");// 查询数据System.out.println("1001 存在?" + mightContain("1001")); // trueSystem.out.println("2001 存在?" + mightContain("2001")); // false}
}

🚀 2. 结合 Redis 缓存 + MySQL 数据库

import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import redis.clients.jedis.Jedis;public class BloomFilterCacheDemo {private static Jedis redisClient = new Jedis("127.0.0.1", 6379);private static RedissonClient redissonClient;private static RBloomFilter<String> bloomFilter;static {// 配置 Redisson 连接 RedisredissonClient = Redisson.create();bloomFilter = redissonClient.getBloomFilter("product_bloom_filter");bloomFilter.tryInit(1000000L, 0.01); // 100w 数据,误判率 1%}/*** 模拟查询数据库*/public static String queryDatabase(String productId) {if ("1001".equals(productId)) {return "商品1001:iPhone 15";} else if ("1002".equals(productId)) {return "商品1002:MacBook Pro";}return null; // 模拟数据库查询不到}/*** 查询商品详情(使用布隆过滤器+Redis缓存)*/public static String getProductInfo(String productId) {// 1️⃣ 先查询布隆过滤器if (!bloomFilter.contains(productId)) {return "商品不存在"; // 直接返回,防止缓存穿透}// 2️⃣ 查询 Redis 缓存String cacheData = redisClient.get("product:" + productId);if (cacheData != null) {return "【缓存】" + cacheData;}// 3️⃣ 查询数据库String dbData = queryDatabase(productId);if (dbData != null) {// 写入 Redis,设置 10 分钟过期redisClient.setex("product:" + productId, 600, dbData);return "【数据库】" + dbData;}return "商品不存在";}public static void main(String[] args) {// 初始化布隆过滤器(模拟数据库已有商品)bloomFilter.add("1001");bloomFilter.add("1002");// 测试查询System.out.println(getProductInfo("1001")); // 【数据库】商品1001:iPhone 15System.out.println(getProductInfo("2001")); // 商品不存在}
}

3. 运行结果

查询商品 IDRedis 缓存数据库布隆过滤器返回结果
1001❌ 无✅ 有✅ 可能存在【数据库】商品1001:iPhone 15
1001(第二次查询)✅ 有-✅ 可能存在【缓存】商品1001:iPhone 15
2001(不存在)❌ 无❌ 无❌ 一定不存在商品不存在

4. 关键点总结

布隆过滤器防止缓存穿透

  • 先用布隆过滤器检查,如果 不在过滤器内,直接返回,避免查询数据库。

Redis 作为缓存

  • 查询时,优先访问 Redis,如果缓存未命中,才访问数据库,并写入 Redis 进行缓存。

误判率低

  • 通过 bloomFilter.tryInit(1000000L, 0.01),设置合理的 n(数据量)和 p(误判率),确保高效过滤。

不能删除数据

  • 布隆过滤器不支持删除,可以用定期重建的方式优化,例如每天重新初始化。

5. 适用场景

🔹 电商系统:防止查询不存在的商品 ID,减少数据库压力。
🔹 用户系统:防止查询不存在的用户 ID,避免账号碰撞攻击。
🔹 API 限流:判断 IP 或 Token 是否在黑名单,快速拒绝非法请求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/73400.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue动态添加或删除DOM元素:购物车实例

Vue 指令系列文章: 《Vue插值:双大括号标签、v-text、v-html、v-bind 指令》 《Vue指令:v-cloak、v-once、v-pre 指令》 《Vue条件判断:v-if、v-else、v-else-if、v-show 指令》 《Vue循环遍历:v-for 指令》 《Vue事件处理:v-on 指令》 《Vue表单元素绑定:v-model 指令》…

vue h5实现车牌号输入框

哈喽&#xff0c;大家好&#xff0c;最近鹏仔开发的项目是学校校内车辆超速方面的统计检测方面的系统&#xff0c;在开发过程中发现有个小功能&#xff0c;就是用户移动端添加车牌号&#xff0c;刚开始想着就一个输入框&#xff0c;提交时正则效验一下格式就行&#xff0c;最后…

硬件基础(5):(3)二极管的应用

文章目录 [toc]1. **整流电路****功能**&#xff1a;**工作原理**&#xff1a;**应用实例**&#xff1a;电路组成&#xff1a;整流过程&#xff1a;电路的应用&#xff1a; 2. **稳压电路****功能**&#xff1a;**工作原理**&#xff1a;**应用实例**&#xff1a;电路组成及功能…

Wireshark网络抓包分析使用详解

序言 之前学计网还有前几天备考华为 ICT 网络赛道时都有了解认识 Wireshark&#xff0c;但一直没怎么专门去用过&#xff0c;也没去系统学习过&#xff0c;就想趁着备考的网络相关知识还没忘光&#xff0c;先来系统学下整理点笔记~ 什么是抓包&#xff1f;抓包就是将网络传输…

安心联车辆管理平台源码价值分析

安心联车辆管理平台源码的价值可从技术特性、功能覆盖、市场适配性、扩展潜力及商业化支持等多个维度进行分析。以下结合实际应用进行详细解读&#xff1a; 一、技术架构与开发优势 主流技术栈与高性能架构 源码采用成熟的前后端分离架构&#xff0c;后端基于Java技术&#xff…

【操作系统】Docker如何使用-续

文章目录 1、概述2、巩固知识2.1、基础命令2.2、容器管理2.3、镜像管理2.4、网络管理2.5、Compose 3、常用命令 1、概述 在使用Docker的过程中&#xff0c;掌握常用的命令是至关重要的。然而&#xff0c;随着时间的推移&#xff0c;我们可能会遗忘一些关键的命令或对其用法变得…

ElementUI el-menu导航开启vue-router模式

有没有小伙伴遇到这么一种情况&#xff1a;ElementUI el-menu导航中&#xff0c;开启vue-router 的模式后&#xff0c;点击触发事件而不进行路由跳转&#xff1f; 别慌&#xff01;下面直接说解决方案&#xff1a; 借助路由守卫进行判断 给el-menu绑定切换事件&#xff0c;给…

【leetcode hot 100 17】电话号码的字母组合

分析&#xff1a;当设计关键字“所有组合”时&#xff0c;要考虑深度优先遍历、广度优先遍历&#xff08;层次遍历&#xff09;&#xff0c;其中&#xff1a; 深度优先搜索&#xff1a; 自顶向下的递归实现深搜定义子问题在当前递归层结合子问题结果解决原问题 广度优先搜索 利…

Vue 2 探秘:visible 和 append-to-body 是谁的小秘密?

&#x1f680; Vue 2 探秘&#xff1a;visible 和 append-to-body 是谁的小秘密&#xff1f;&#x1f914; 父组件&#xff1a;identify-list.vue子组件&#xff1a;fake-clue-list.vue 嘿&#xff0c;各位前端探险家&#xff01;&#x1f44b; 今天我们要在 Vue 2 的代码丛林…

C++学习之路:从头搞懂配置VScode开发环境的逻辑与步骤

目录 编辑器与IDE基于vscode的C开发环境配置1. 下载vscode、浅尝编译。番外篇 2. 安装插件&#xff0c;赋能编程。3. 各种json文件的作用。c_cpp_properties.jsontask.jsonlaunch.json 总结&&彩蛋 编辑器与IDE 上一篇博客已经介绍过了C程序的一个编译流程&#xff0c;从…

PPT 转高精度图片 API 接口

PPT 转高精度图片 API 接口 文件处理 / 图片处理&#xff0c;将 PPT 文件转换为图片序列。 1. 产品功能 支持将 PPT 文件转换为高质量图片序列&#xff1b;支持 .ppt 和 .pptx 格式&#xff1b;保持原始 PPT 的布局和样式&#xff1b;转换后的图片支持永久访问&#xff1b;全…

VSCode 抽风之 两个conda环境同时在被激活

出现了神奇的(toolsZCH)(base) 提示符&#xff0c;如下图所示&#xff1a; 原因大概是&#xff1a;conda 环境的双重激活&#xff1a;可能是 conda 环境没有被正确清理或初始化&#xff0c;导致 base 和 toolsZCH 同时被激活。 解决办法就是 &#xff1a;conda deactivate 两次…

git | 回退版本 并保存当前修改到stash,在进行整合。[git checkout | git stash 等方法 ]

目录 一些常见命令&#xff1a; git 回退版本 一、临时回退&#xff08;不会修改历史&#xff0c;可随时回到当前版本&#xff09; 方法1&#xff1a;git checkout HEAD~1 问题&#xff1a;处于 detached HEAD 状态下提交的&#xff0c;无法直接 git push ✅ 选项 1&…

如何使用 Postman 进行接口测试?

使用 Postman 这一工具&#xff0c;可以轻松地进行接口测试。以下是一份简单的使用教程&#xff0c;帮助你快速上手。 Postman 接口测试教程&#xff1a;详细步骤及操作技巧

写作软件新体验:让文字创作更高效

一、开篇引入:写作难题的破解之道 在当今信息爆炸的时代,写作成为了我们生活和工作中不可或缺的一部分。然而,面对繁琐的写作任务,我们时常感到力不从心,甚至陷入创作的瓶颈。那么,有没有一款软件能够帮助我们破解这一难题,让文字创作变得更加高效和轻松呢?答案是肯定…

大模型思维链COT:Chain-of-Thought Prompting Elicits Reasoningin Large Language Models

一、TL&#xff1b;DR 探索了COT&#xff08;chain-of-thought prompting&#xff09;通过一系列的中间推理步骤来显著的提升了LLM的复杂推理能力在三个大型语言模型上的实验表明&#xff0c;思维链提示能够提升模型在一系列算术、常识和符号推理任务上的表现解释了一下为什么…

systemd-networkd的配置文件的优先级 笔记250325

systemd-networkd的配置文件的优先级 systemd-networkd的配置文件优先级规则如下&#xff1a; 1. 目录优先级 配置文件按以下目录顺序加载&#xff08;优先级从高到低&#xff09;&#xff1a; /etc/systemd/network&#xff08;用户自定义配置&#xff0c;最高优先级&#x…

详细说明windows系统函数::SetUnhandledExceptionFilter(ExceptionFilter)

::SetUnhandledExceptionFilter(ExceptionFilter); 是 Windows 编程中用于设置顶层未处理异常过滤器的关键 API 调用。它属于 Windows 结构化异常处理&#xff08;SEH, Structured Exception Handling&#xff09;机制的一部分&#xff0c;主要用于捕获那些未被程序内部处理的异…

决策树算法详解:从西瓜分类到实战应用

目录 0. 引言 1. 决策树是什么&#xff1f; 1.1 生活中的决策树 1.2 专业版决策树 2. 如何构建决策树&#xff1f; 2.1 关键问题&#xff1a;选哪个特征先判断&#xff1f; 2.1.1 信息熵&#xff08;数据混乱度&#xff09; 2.1.2 信息增益&#xff08;划分后的整洁度提…

超融合服务器是什么

超融合服务器的定义与背景 超融合服务器&#xff08;Hyperconverged Infrastructure, HCI&#xff09;是一种通过软件定义技术&#xff0c;将计算、存储、网络和虚拟化功能整合到单一硬件平台中的IT基础设施解决方案。其核心目标是通过资源的高度集成和统一管理&#xff0c;简…