这年轻人,在JAVA项目中使用布隆过滤器
提要
布隆过滤器(Bloom Filter)相信大家都听说过,不了解的朋友可以参考我之前的文章《布隆过滤器简介》。那么在Java项目中怎样使用布隆过滤器呢,下面就简单介绍下。
一. 使用Guava中提供的布隆过滤器
Guava是一套Google开源的Java库,它提供了很多简化编程的工具类,其中就包括了布隆过滤器。
使用方式
- 在项目中添加依赖
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>29.0-jre</version>
</dependency>
- 代码示例
package com.example;
import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
import java.nio.charset.Charset;
/**
* 使用Guava提供的布隆过滤器
*/
public class GuavaBloomFilter {
// 预计存储元素的个数
private static final int expectedInsertions = 10000;
// 误判率
private static final double fpp = 0.03;
public static void main(String[] args) {
// 创建布隆过滤器
BloomFilter<CharSequence> bloomFilter = BloomFilter.create(
Funnels.stringFunnel(Charset.defaultCharset()), expectedInsertions, fpp);
// 存入元素
bloomFilter.put("张三");
bloomFilter.put("李四");
System.out.println("大约存储元素的个数:" + bloomFilter.approximateElementCount());
// 检索元素
System.out.println("检索张三是否存在:" + bloomFilter.mightContain("张三"));
System.out.println("检索王五是否存在:" + bloomFilter.mightContain("王五"));
}
}
注意:Guava提供的布隆过滤器只能应用在单体应用中,因为这种方式创建的过滤器是存储在应用内存中的,所以在分布式环境下不适用。
二. 使用Redis中加载的布隆过滤器模块
在分布式环境下,使用Redis存储布隆过滤器就是个不错的选择。从Redis4.0版本开始,可以通过加载Redis实验室提供的布隆过滤器模块,使Redis中具有布隆过滤器类型。
使用此种方式操作布隆过滤器有个必要的前提:Redis Server必须加载布隆过滤器模块。加载方法可以参考我之前的文章《Redis加载布隆过滤器模块》。
一般我们在Java项目中连接Redis时通常是使用Jedis客户端,但是目前Jedis中没有提供对Redis扩展模块的命令的封装,所以我们必须使用Redis实验室提供的专门操作扩展模块的客户端。
使用方式
- 在项目中添加依赖
<dependency>
<groupId>com.redislabs</groupId>
<artifactId>jrebloom</artifactId>
<version>2.1.0</version>
</dependency>
- 代码示例
package com.example;
import io.rebloom.client.Client;
import io.rebloom.client.ClusterClient;
import redis.clients.jedis.HostAndPort;
import java.util.HashSet;
import java.util.Set;
/**
* 使用Redis布隆过滤器模块
*/
public class RedisModuleBloomFilter {
// 容量
private static final long initCapacity = 10000L;
// 误判率
private static final double errorRate = 0.03;
private static final String FILTER_NAME = "BF:name"
public static void main(String[] args) {
// 初始化客户端
Client client = new Client("localhost", 6379);
// // 初始化集群客户端
// Set<HostAndPort> clusterNodes = new HashSet<>();
// clusterNodes.add(new HostAndPort("localhost", 6379));
// ClusterClient client = new ClusterClient(clusterNodes);
// 创建布隆过滤器;该方法只能调用一次,如果同名过滤器已存在,将抛出异常
client.createFilter(FILTER_NAME, initCapacity, errorRate);
// 添加单个元素
client.add(FILTER_NAME, "mark");
// 添加多个元素
client.addMulti(FILTER_NAME, "foo", "bar", "baz", "bat", "bag");
// 检查元素是否存在
System.out.println(client.exists(FILTER_NAME, "mark"));
System.out.println(client.exists(FILTER_NAME, "foot"));
}
}
三. 使用Redisson提供的基于Redis布隆过滤器
Redisson是一款功能强大且简单易用的Java语言的Redis客户端。
强烈建议没有使用过的朋友可以学习一下。GitHub地址:https://github.com/redisson/redisson。值得一提的是,该项目还提供了中文文档(https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95),这对英文不好的朋友可以说是很大的福音了。
使用Redisson客户端提供的布隆过滤器功能可以直接在Redis中创建及使用布隆过滤器,无需在Redis Server中加载扩展模块。
使用方式
- 在项目中添加依赖
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.13.6</version>
</dependency>
- 代码示例
package com.example;
import org.redisson.Redisson;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
/**
* 使用redisson布隆过滤器
*/
public class RedissonBloomFilter {
// 预计存储元素的个数
private static final long expectedInsertions = 10000L;
// 误判率
private static final double fpp = 0.03;
private static final String FILTER_NAME = "BF:name";
public static void main(String[] args) {
// 创建redisson连接
Config config = new Config();
config.useSingleServer().setTimeout(1000000).setAddress("redis://localhost:6379");
RedissonClient redissonClient = Redisson.create(config);
// 创建布隆过滤器并初始化
RBloomFilter<String> bloomFilter = redissonClient.getBloomFilter(FILTER_NAME);
bloomFilter.tryInit(expectedInsertions, fpp);
// 存入元素
bloomFilter.add("张三");
bloomFilter.add("李四");
// 检索元素是否存在
System.out.println(bloomFilter.contains("张三"));
System.out.println(bloomFilter.contains("王五"));
// 关闭连接
redissonClient.shutdown();
}
}