在当今高并发、海量数据的应用场景中,布隆过滤器凭借其极低的内存占用和极快的查询效率,成为解决缓存穿透、数据预判等难题的利器。本文深度解析布隆过滤器的核心原理与实战应用,手把手教你如何将这一数据守门员融入实际项目。

一、布隆过滤器简介

布隆过滤器(Bloom Filter)是一种高效的概率型数据结构,用于快速判断元素是否存在于集合中。其核心是一个二进制向量和多个哈希函数,具有以下特点:

  • 空间效率高:占用的内存远小于传统数据结构(如哈希表)。
  • 查询速度快:时间复杂度为O(k)(k为哈希函数数量)。
  • 存在误判率:可能将不存在的元素误判为存在,但不会漏判存在的元素。

二、使用场景分析

  1. 缓存穿透解决方案

    缓存穿透指大量请求查询不存在的数据(如无效ID),绕过缓存直接访问数据库,导致数据库压力骤增甚至崩溃。布隆过滤器通过以下流程拦截非法请求:

    • 初始化阶段:将数据库所有有效数据的键(如用户ID)预加载到布隆过滤器中。
    • 查询阶段:请求先经过布隆过滤器判断键是否存在。若不存在则直接返回空结果;若存在,再查询缓存或数据库。
    • 优势:显著减少无效数据库查询,结合空值缓存(缓存不存在的结果)和分布式锁(防止并发重建缓存),可构建多层防护。
  2. 其他典型场景
    • 数据去重:如防止重复用户名注册。
    • 爬虫URL过滤:避免重复抓取同一链接。
    • 推荐系统:拦截无历史行为用户的无效请求。
    • 防止重复提交:判断请求ID是否已处理。

三、Spring Boot集成Redisson实现布隆过滤器

Redisson是Java生态中功能丰富的Redis客户端,提供分布式布隆过滤器实现,支持多节点共享和自动容错,以下是完整代码示例:

1. 添加依赖

pom.xml中引入Redisson依赖:

<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.16.6</version>
</dependency>
2. 配置Redisson客户端

创建配置类RedissonConfig

@Configuration
public class RedissonConfig {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private String port; @Bean
public RedissonClient redissonClient() {
Config config = new Config();
config.useSingleServer()
.setAddress("redis://" + host + ":" + port);
return Redisson.create(config);
}
}
3. 初始化布隆过滤器

在服务启动时加载数据:

@Service
public class BloomFilterService {
@Resource
private RedissonClient redissonClient;
@Resource
private DataService dataService; @PostConstruct
public void initBloomFilter() {
RBloomFilter<String> bloomFilter = redissonClient.getBloomFilter("userFilter");
bloomFilter.tryInit(1000000L, 0.01); // 预期数据量100万,误判率1%
List<String> ids = dataService.getAllIds();
ids.forEach(bloomFilter::add);
}
}
4. 在业务流程中使用布隆过滤器

在查询逻辑中添加过滤器检查:

public User getUserById(String id) {
RBloomFilter<String> bloomFilter = redissonClient.getBloomFilter("userFilter");
// 步骤1:检查布隆过滤器
if (!bloomFilter.contains(id)) {
return null; // 直接拦截不存在的数据
}
// 步骤2:查询缓存
User user = redisTemplate.opsForValue().get("user:" + id);
if (user != null) {
return user;
}
// 步骤3:查询数据库
user = userRepository.findById(id);
if (user != null) {
redisTemplate.opsForValue().set("user:" + id, user, 30, TimeUnit.MINUTES);
} else {
// 缓存空值,防止重复查询数据库
redisTemplate.opsForValue().set("user:" + id, NullValue.DEFAULT, 5, TimeUnit.MINUTES);
}
return user;
}

四、注意事项与优化

  1. 误判率控制

    • 误判率与哈希函数数量、位数组大小相关。Redisson通过tryInit()自动计算参数,需根据业务调整预期元素数量和可接受的误判率。
    • 增加哈希函数次数可降低误判,但会牺牲性能。
  2. 数据同步
    • 初始化需预加载全量数据,适用于静态或低频更新场景。动态数据需通过定时任务刷新过滤器。
    • 不支持删除操作,需通过重建过滤器或结合其他数据结构(如Counting Bloom Filter)实现。

五、总结

布隆过滤器以极小的空间代价解决了缓存穿透等高频查询问题,结合Redisson可快速实现分布式场景下的高效防护。开发者需权衡误判率、初始化成本与业务需求,选择适合的配置方案。在复杂场景中,可将其与空值缓存、分布式锁组合,构建稳定性更强的系统。

SpringBoot + 布隆过滤器:亿级数据下的高效防护盾与缓存穿透实战指南的更多相关文章

  1. 基于Mysql数据库亿级数据下的分库分表方案

    移动互联网时代,海量的用户数据每天都在产生,基于用户使用数据的用户行为分析等这样的分析,都需要依靠数据都统计和分析,当数据量小时,问题没有暴露出来,数据库方面的优化显得不太重要,一旦数据量越来越大时, ...

  2. Redis: 缓存过期、缓存雪崩、缓存穿透、缓存击穿(热点)、缓存并发(热点)、多级缓存、布隆过滤器

    Redis: 缓存过期.缓存雪崩.缓存穿透.缓存击穿(热点).缓存并发(热点).多级缓存.布隆过滤器 2019年08月18日 16:34:24 hanchao5272 阅读数 1026更多 分类专栏: ...

  3. python实现布隆过滤器及原理解析

    python实现布隆过滤器及原理解析     布隆过滤器( BloomFilter )是一种数据结构,比较巧妙的概率型数据结构(probabilistic data structure),特点是高效地 ...

  4. SpringBoot(18)---通过Lua脚本批量插入数据到Redis布隆过滤器

    通过Lua脚本批量插入数据到布隆过滤器 有关布隆过滤器的原理之前写过一篇博客: 算法(3)---布隆过滤器原理 在实际开发过程中经常会做的一步操作,就是判断当前的key是否存在. 那这篇博客主要分为三 ...

  5. 布隆过滤器 - 如何在100个亿URL中快速判断某URL是否存在?

    题目描述 一个网站有 100 亿 url 存在一个黑名单中,每条 url 平均 64 字节.这个黑名单要怎么存?若此时随便输入一个 url,你如何快速判断该 url 是否在这个黑名单中? 题目解析 这 ...

  6. 一道腾讯面试题:如何快速判断某 URL 是否在 20 亿的网址 URL 集合中?布隆过滤器

    何为布隆过滤器 还是以上面的例子为例: 判断逻辑: 多次哈希: Guava的BloomFilter 创建BloomFilter 最终还是调用: 使用: 算法特点 使用场景 假设遇到这样一个问题:一个网 ...

  7. 挑战海量数据:基于Apache DolphinScheduler对千亿级数据应用实践

    点亮 ️ Star · 照亮开源之路 GitHub:https://github.com/apache/dolphinscheduler 精彩回顾 近期,初灵科技的大数据开发工程师钟霈合在社区活动的线 ...

  8. 布隆过滤器(Bloom Filter)详解——基于多hash的概率查找思想

    转自:http://www.cnblogs.com/haippy/archive/2012/07/13/2590351.html   布隆过滤器[1](Bloom Filter)是由布隆(Burton ...

  9. 布隆过滤器(Bloom Filter)的原理和实现

    什么情况下需要布隆过滤器? 先来看几个比较常见的例子 字处理软件中,需要检查一个英语单词是否拼写正确 在 FBI,一个嫌疑人的名字是否已经在嫌疑名单上 在网络爬虫里,一个网址是否被访问过 yahoo, ...

  10. [转载] 布隆过滤器(Bloom Filter)详解

    转载自http://www.cnblogs.com/haippy/archive/2012/07/13/2590351.html   布隆过滤器[1](Bloom Filter)是由布隆(Burton ...

随机推荐

  1. (十).NET6.0 搭建基于Quartz组件的定时调度任务

    1.添加Quartz定时器组件 2.新建类库项目Wsk.Core.QuartzNet,并且引用包类库项目.然后新建一个中间调度类,叫QuartzMiddleJob 3.新建一个Job工厂类,叫YsqJ ...

  2. [Java] 计算Java对象大小

    序 在Java应用程序的性能优化场景中,时常需要考虑Java对象的大小,以便评估后,进一步提出优化方案: 占用内存的大小.(比如 本地内存) 对象数据在网络传输中占用的网络带宽 对象数据在存储时占用的 ...

  3. WPF 设置Button的content为多行模式

    查找button的子元素是个TextBlock,再设置它的TextWrappingProperty属性为 TextWrapping.Wrap. Button btn2 = new Button() { ...

  4. w3cschool-Django中文教程

    https://www.w3cschool.cn/django/ Django 简介 Django 是用Python开发的一个免费开源的Web框架,可以用于快速搭建高性能,优雅的网站!采用了MVC的框 ...

  5. 抽取网易云音乐热门评论:html+css+python+js 音乐与灵魂的碰撞

    抽取网易云音乐热门评论:html+css+python+js 音乐与灵魂的碰撞 代码链接 不说废话,上代码!!! get.py # get.py import urllib.request impor ...

  6. ubuntu配置笔记

    一.ubuntu的mnt/hgfs下共享文件夹设置 1.确认VMware Tools和共享目录设定已经完成,安装vmware tool sudo apt-get install open-vm-too ...

  7. Q:oracle中blog中截取部分字符串

    blog报文中获取对应标签字符串 将xxx替换成需要查询的标签 to_char(substr(C_INPUT,instr(C_INPUT,'<xxx>')+length('<xxx& ...

  8. tortoiseGit no git.exe found

    运行tortoiseGit之后显示找不到git.exe 原因:没有安装git,tortoiseGit是在安装了git的基础上运行的 到这里下载git并安装:https://gitforwindows. ...

  9. 【Unity】热更新原理与Xlua配置

    [Unity]热更新原理与 Xlua 配置 热更新 直接理解即是让代码可以像资源包一样被运行时更新.当然它其实还一个名称叫热修复,即实现不重新打包项目也能把 Bug 修好,这也正是它常用的地方. 原理 ...

  10. DW005 - ArgoDB基础

    第1章 Argo基础 1.1 ArgoDB对象 说明 在ArgoDB中,可以使用常见的数据库对象,包括数据库(Database),表(Table),视图(View)和函数(Function) 可以使用 ...