单机版-Guava
引入guava依赖:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>
测试:
@Test
public void test2() {
BloomFilter<Integer> filter = BloomFilter.create(Funnels.integerFunnel(), 100);
System.out.println(filter.mightContain(1));
System.out.println(filter.mightContain(2));
filter.put(1);
filter.put(2);
System.out.println(filter.mightContain(1));
System.out.println(filter.mightContain(2));
}
此外BloomFilter.create方法还可以增加一个误判率的参数,实际guava底层的误判率是0.03
public static <T extends @Nullable Object> BloomFilter<T> create(
Funnel<? super T> funnel, long expectedInsertions) {
return create(funnel, expectedInsertions, 0.03); // FYI, for 3%, we always get 5 hash functions
}
Guava中的布隆过滤器只能单机使用,现在互联网公司一般都是分布式。
Redis版布隆过滤器
布隆过滤器解决缓存穿透的流程图如下:
引入redisson依赖:
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.12.5</version>
</dependency>
布隆过滤器的使用:
@SpringBootTest
class RedisApplicationTests {
private static RedissonClient redissonClient;
private static RBloomFilter<Object> bloomFilter;
private static long size = 1000000;
private static double fpp = 0.01;
@BeforeAll
public static void before() {
Config config = new Config();
config.useSingleServer().setAddress("redis://xxx.xxx.xxx.xxx").setDatabase(0).setPassword("xxxxxxxx");
redissonClient = Redisson.create(config);
bloomFilter = redissonClient.getBloomFilter("myBloomFilter", new StringCodec());
bloomFilter.tryInit(size, fpp);
bloomFilter.add("10000");
}
@Test
void contextLoads() {
Assertions.assertTrue(bloomFilter.contains("10000"));
Assertions.assertFalse(bloomFilter.contains("10001"));
}
}
运行结束后,redis中也会存在布隆过滤器的相关配置:
Docker安装RedisBloom
redis在4.0之后有了插件的功能(Module),可以使用外部的扩展功能,可以使用RedisBloom作为redis布隆过滤器插件。
此外也可以使用Docker安装RedisBloom。
docker run -p 6380:6379 -itd --name redis-redisbloom redislabs/rebloom:latest
执行命令:
docker exec -it redis-redisbloom redis-cli
127.0.0.1:6379> BF.ADD newFilter foo
(integer) 1
127.0.0.1:6379> BF.EXISTS newFilter foo
(integer) 1
127.0.0.1:6379> BF.EXISTS newFilter foo1
(integer) 0