布隆过滤器主要是为了解决海量数据的存在性问题,对于海量数据中判定某个数据是否存在且容忍轻微误差的场景(比如缓存穿透、海量数据去重)来说,非常适合
什么是布隆过滤器?用于解决什么问题
布隆过滤器时一种概率型的数据结构,用于快速判断一个元素是否属于某个集合,通过使用多个哈希函数和位数组来存储元素的信息。
布隆过滤器用于检索一个元素是否在一个集合中。
- 优点:空间效率和查询时间都远远超过一半的算法
- 缺点:有一定的误判率,不支持删除
解决缓存穿透的问题
布隆过滤器的基本原理
- 初始化:创建一个长度为m的位数组,初始时所有位都置为0
- 添加元素:将要添加的元素通过多个不同的哈希函数映射到位数组上的位置,并将对应的位设置为1
- 查询元素:查询一个元素时,同样地使用多个哈希函数映射到位数组上的位置,如果所有对应的位都为1,则说明该元素可能存在于集合中,如果任意一个位为0,则说明该元素不一定存在于集合中。
在Java中的使用
导入redisson依赖包
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.17.3</version>
</dependency>
代码示例
@Test
public void test5() {
Config config = new Config();
config.useSingleServer().setAddress("redis://172.16.67.37:6379");
RedissonClient cient = Redisson.create(config);
RBloomFilter<String> bloomFilter = cient.getBloomFilter("test5-bloom-filter");
// 初始化布隆过滤器,数组长度100W,误判率 1%
bloomFilter.tryInit(1000000L, 0.01);
// 添加数据
bloomFilter.add("aaa");
// 判断是否存在
System.out.println(bloomFilter.contains("bbbb"));
System.out.println(bloomFilter.contains("aaa"));
}
运行结果:
false // 肯定不存在
true // 可能存在,有1%的误判率
注意:误判率设置过小,会产生更多次的 Hash 操作,降低系统的性能。通常我们的建议值是 1%
布隆过滤器的处理流程
- 把所有可能存在的请求的值都存放在布隆过滤器中,当用户请求过来,先判断用户发来的请求值是否存在于布隆过滤器中,不存在的话直接返回请求参数错误给客户端,存在的话走如下流程。
- 加入布隆过滤器之后的缓存处理流程图如下。