当前位置: 首页 > news >正文

使用Redission来实现布隆过滤器

简述布隆过滤器

布隆过滤器是一种概率型数据结构,它可以用来判断一个元素是否在一个集合中。我们当时使用的是Redisson实现的布隆过滤器。它的底层原理是,先初始化一个比较大的数组,里面存放的是二进制0或1。一开始都是0,当一个key来了之后,经过3次hash计算,模数组长度找到数据的下标,然后把数组中原来的0改为1。这样,三个数组的位置就能标明一个key的存在。当需要判断一个元素是否存在时,通过相同的哈希函数计算出该元素在位数组上的位置,如果这些位置上的值都为1,则认为该元素可能存在;如果任何一个位置上的值为0,则该元素一定不存在。在缓存穿透的场景中,我们可以将数据库中存在的数据对应的key存入布隆过滤器,当查询一个key时,先通过布隆过滤器判断该key是否存在,如果不存在,直接返回,避免查询数据库。

为什么会产生误判

误判的产生是由于多个不同的元素可能通过哈希函数映射到位数组的相同位置。这种情况称为哈希冲突。由于布隆过滤器使用多个哈希函数,一个元素的每个哈希值都对应位数组中的一个位置,这意味着不同元素的哈希值可能会重叠。

例如,如果两个不同的元素通过哈希函数计算后都映射到位数组的同一个位置,并且这个位置最初是0,那么当第一个元素被添加到布隆过滤器时,该位置会被设置为1。当第二个元素被检查时,由于该位置已经是1,布隆过滤器可能会错误地认为第二个元素也存在于集合中,即使它实际上并不存在。

减少误判的方法

  1. 增加位数组的大小:更大的位数组可以减少哈希冲突的概率,从而降低误判率。

  2. 增加哈希函数的数量:更多的哈希函数可以更均匀地分布元素到位数组中,但也会增加计算成本。

  3. 选择合适的哈希函数:好的哈希函数可以减少冲突的概率。

布隆过滤器怎么更新和删除内容,有实现的思路吗?

布隆过滤器是一种只支持添加元素,理论上不支持删除元素的数据结构,因为它使用多个哈希函数将元素映射到位数组的多个位置,删除一个元素可能会影响其他元素的检查结果。不过,有一些方法可以间接实现删除操作或者更新布隆过滤器的内容。

1. 重新创建布隆过滤器

最简单直接的方法是重新创建一个布隆过滤器,将需要保留的元素重新添加进去。这种方法成本较高,因为它需要重新计算所有保留元素的哈希值并更新位数组。

2. 使用计数器(Counting Bloom Filter)

计数布隆过滤器(Counting Bloom Filter)是布隆过滤器的一种变体,它使用计数数组代替位数组,每个位置存储一个计数值而不是简单的0或1。这样,删除元素时可以将对应位置的计数值减1,而不是直接置为0。这种方法可以支持删除操作,但增加了存储空间和计算复杂度。

使用Redission来实现布隆过滤器的步骤

 1. 添加Redission依赖

<dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.15.6</version> <!-- 请检查最新版本 -->
</dependency>

2. 配置Redission

在应用启动时,配置Redisson客户端以连接到Redis服务器:

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;public class RedissonConfig {public static RedissonClient create() {Config config = new Config();config.useSingleServer().setAddress("redis://127.0.0.1:6379"); // Redis服务器地址return Redisson.create(config);}
}

3. 使用Redisson创建和使用布隆过滤器

import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;public class BloomFilterExample {private static final RedissonClient redisson = RedissonConfig.create();public static void main(String[] args) {// 创建布隆过滤器,预计元素数量为1000,误判率为0.03RBloomFilter<String> bloomFilter = redisson.getBloomFilter("myBloomFilter");bloomFilter.tryInit(1000, 0.03);// 添加元素到布隆过滤器bloomFilter.add("key1");bloomFilter.add("key2");// 检查元素是否存在于布隆过滤器boolean exists1 = bloomFilter.contains("key1"); // 应该返回trueboolean exists2 = bloomFilter.contains("key2"); // 应该返回trueboolean exists3 = bloomFilter.contains("key3"); // 可能返回false或true(误判)System.out.println("key1 exists: " + exists1);System.out.println("key2 exists: " + exists2);System.out.println("key3 exists: " + exists3);}
}

4. 处理缓存穿透

在缓存穿透的场景中,使用布隆过滤器来避免不必要的数据库查询

import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;public class CacheService {// 获取Redisson客户端实例,确保已经配置好Redissonprivate static final RedissonClient redisson = RedissonConfig.create();// 使用Redisson创建布隆过滤器,名称为"myBloomFilter"private static final RBloomFilter<String> bloomFilter = redisson.getBloomFilter("myBloomFilter");/*** 获取数据的方法。* 先通过布隆过滤器检查key是否存在,如果不存在则直接返回null。* 如果存在,从数据库查询数据,并在查询到数据后将key添加到布隆过滤器中。* @param key 要查询的key* @return 查询到的数据,如果不存在则返回null*/public String getData(String key) {// 检查布隆过滤器,如果key不存在,则直接返回nullif (!bloomFilter.contains(key)) {return null;}// 从数据库查询数据String data = queryDatabase(key);// 如果查询到数据,且该key尚未在布隆过滤器中,则添加到布隆过滤器if (data != null && !bloomFilter.contains(key)) {bloomFilter.add(key);}return data;}/*** 模拟从数据库查询数据的方法。* 实际应用中,这里应该是数据库查询逻辑。* @param key 要查询的key* @return 查询到的数据*/private String queryDatabase(String key) {// 这里模拟数据库查询,实际应用中应替换为数据库查询逻辑// 假设数据库中存在key对应的数据return "some data for " + key;}
}
http://www.xdnf.cn/news/517609.html

相关文章:

  • 【八股战神篇】MySQL高频面试题
  • FreeTex v0.3.0:支持静默运行/软件体积压缩
  • LLM笔记(八)Transformer学习
  • 2025年- H29-Lc137- 19.删除链表的倒数第N个节点(快慢指针)---java版
  • WebSocket解决方案的一些细节阐述
  • 国内人工智能行业研究报告 目录
  • 三相逆变器下垂均流控制策略simulink仿真
  • 通过觅思文档项目实现Obsidian文章浏览器在线访问
  • 基于OpenCV的实时文档扫描与矫正技术
  • Embedding 模型详解:架构、训练与 LLM 的区别
  • Opik: 评估、测试和监控 LLM 应用
  • 进程相关概念总结
  • Windows系统各版本环境变量
  • # 08_Elastic Stack 从入门到实践(八)---2
  • 关于文件分片的介绍和应用
  • Linux基础第三天
  • 例举3种强制类型转换和2种隐式
  • |从零开始的Pyside2界面编程| 环境搭建以及第一个ui界面
  • 系统思考:IT企业项目困境分析
  • 基于Java+MySQL+Servlet的留言系统开发全解析
  • 电子电路:怎么理解电子在导体中的热运动?
  • C++数组详解:一维和多维数组的定义、初始化、访问与遍历
  • 算法优化——以“LCR 080. 组合”为例
  • React Native打包报错: Task :react-native-picker:verifyReleaseResources FAILE
  • IIS入门指南:原理、部署与实战
  • 电动车仪表上的数字怎么来的,想知道吗?
  • leetcode3546. 等和矩阵分割 I- medium
  • uniapp中的easycom工作机制
  • Flask快速入门和问答项目源码
  • ​在 ASP.NET 中,HTTP 处理程序(HttpHandler)是处理 HTTP 请求的核心组件​