您的位置 首页 java

Redis实现布隆过滤器(下)

Redis实现布隆过滤器(下)

Redis4.0通过模块化的形式集成了布隆过滤器,后续通过下面的命令就可以操作布隆过滤器,路径

那么我们怎么通过Java代码去操作布隆过滤器呢?

RedisBloom官网提出了三种直接操作Redis布隆过滤器模块的方式,相关资料参考,其中JreBloom已经弃用暂不讨论。

注意:远程连接时redis.conf配置文件中需要关闭受保护模式 protected-mode no

Jedis支持布隆过滤器

jedis是专门为Redis设计的简单易用性客户端,同时最新版本也支持模块化服务如布隆过滤器

引入依赖

 <dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>4.2.0</version>
</dependency>
  

测试代码

 public class JedisDemo {
    public static void main(String[] args) throws URISyntaxException {
        // 建立连接
        BloomFilterCommands bloomFilterCommands = new JedisPooled(new URI("redis://47.99.147.139:6379"),1000000);
        // 构建布隆过滤器参数
        BFReserveParams bfReserveParams = new BFReserveParams();
        bfReserveParams.expansion(2);
        // 创建一个过滤器
        String test = bloomFilterCommands.bfReserve("test", 0.1, 100, bfReserveParams);
        // 向过滤器中添加元素
        bloomFilterCommands.bfAdd("test",String.valueOf(1));
        // 判断元素是否存在
        boolean isExist = bloomFilterCommands.bfExists("test", "1");
        System.out.println(isExist);
    }
}
  

其余功能性API可以通过官方文档查阅。

redis-modules支持布隆过滤器

redis-modules是基于Java的客户端,依赖于redisson,所以也需要引入redisson依赖。

引入依赖

 <!-- 引入redisson依赖 -->
<dependency>
   <groupId>org.redisson</groupId>
   <artifactId>redisson</artifactId>
   <version>3.17.1</version>
</dependency>  
<!-- release  这里是引入所有支持的module-->
<dependency>
    <groupId>io.github.dengliming.redismodule</groupId>
    <artifactId>all</artifactId>
    <version>2.0.0</version>
</dependency>
<!-- 也可以只引入单一的module:如布隆过滤器,两者选其一即可 -->
<dependency>
    <groupId>io.github.dengliming.redismodule</groupId>
    <artifactId>redisbloom</artifactId>
    <version>2.0.0</version>
</dependency>
  

测试代码

 public static void main(String[] args) {
    // redisson创建连接一样的写法,需要引入redisson依赖
    Config config = new Config();
    config.useSingleServer().setAddress("redis://127.0.0.1:6379");
    RedisBloomClient redisBloomClient = new RedisBloomClient(config);
    // 得到指定名字的布隆过滤器对象
    BloomFilter bloomFilter = redisBloomClient.getRBloomFilter("bf");
    // 指定布隆过滤器错误率和容量
    bloomFilter.create(0.1d, 100);
    // 向布隆过滤器中添加元素
    bloomFilter.madd(new String[] {"a", "b", "c"});
    // 批量判断元素是否存在类似BF.MEXISTS
    List<Boolean> booleans = bloomFilter.existsMulti("a", "b", "d");
    System.out.println(booleans);
    // 关闭客户端
    redisBloomClient.shutdown();
}
  

redis布隆过滤器命令和Java代码对应可以参考官方在线链接

上面提到的jedis和redis-modules支持布隆过滤器,存储到redis中也是布隆过滤器的形式

但除了这种形式外,还有其它的方法去实现布隆过滤器,如redisson不需要采用redis集成的redis-bloom就可以实现布隆过滤器。

Redisson支持布隆过滤器

引入依赖

 <dependency>
   <groupId>org.redisson</groupId>
   <artifactId>redisson</artifactId>
   <version>3.17.1</version>
</dependency>  
  

测试连接代码

 public static void main(String[] args) {
    // 1. Create config object
    Config config = new Config();
    /** 根据redis实例模式选择对于实例化方法
       * 集群模式:useClusterServers
       * 单实例模式:useSingleServer
       * Sentinel 模式:useSentinelServers
       * 主从模式:useMasterSlaveServers
       */
    config.useSingleServer().setAddress("redis://47.99.147.139:6379");
    // 2. Create Redisson instance
    RedissonClient redisson = Redisson.create(config);
    RBloomFilter bloomFilter = redisson.getBloomFilter("sample");
    // initialize bloom filter with 在使用前必须使用tryInit初始化
    // expectedInsertions = 55000000 期望值
    // falseProbability = 0.03 错误率
    bloomFilter.tryInit(10, 0.03);
    bloomFilter.add("1001");
    System.out.println(bloomFilter.contains("1002"));
    redisson.shutdown();
}
  

执行完上述代码后我们可以查看redis中存储的数据

 ### redisson执行bloomFilter.tryInit,并且成功,
### 不往布隆过滤器中添加元素那么redis只有一个值{**}:config
127.0.0.1:6379> keys *
1) "{sample}:config"
### 查看存入值的类型
127.0.0.1:6379> type "{sample}:config"
hash
127.0.0.1:6379> HKEYS "{sample}:config"
1) "size" ### 二进制bit数组长度 
2) "hashIterations" ### 哈希函数的个数
3) "expectedInsertions" ### 容量
4) "falseProbability" ### 错误率
127.0.0.1:6379> hget "{sample}:config" "size"
"72"
127.0.0.1:6379> hget "{sample}:config" "hashIterations"
"5"
127.0.0.1:6379> hget "{sample}:config" "expectedInsertions"
"10"
127.0.0.1:6379> hget "{sample}:config" "falseProbability"
"0.03"
#### 存放真正值
127.0.0.1:6379> type sample
string
  

redisson会生成两个键值{sample}:config和sample,其中{sample}:config是哈希类型,用于存储用户配置的布隆过滤器配置,sample为string类型,用于存储真实的bit数组。

那么除了依赖redis还有没有办法去实现布隆过滤器呢?当然Google就开源出了guava工具类就可以实现布隆过滤器。

Guava实现布隆过滤器

guava是谷歌开源工具类,其中就有能直接实现布隆过滤器的方法,不需要重复造轮子。

引入依赖

 <dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>31.1-jre</version>
</dependency>
  

测试代码

 public static void main(String[] args) {
    int num = 100000;
    // 创建布隆过滤器对象,误判率默认0.03,可以指定
    // num表示布隆过滤器的容量
    BloomFilter bloomFilter = BloomFilter.create(Funnels.integerFunnel(),num,0.01);
    // 往布隆过滤器中添加数据
    for (int i = 0; i <num ; i++) {
        bloomFilter.put(i);
    }
    // 判断刚添加进去的值误判情况
    for (int i = 0; i <num ; i++) {
        // mightContain 判断布隆过滤器是否包含对象
        if (!bloomFilter.mightContain(i)){
            System.out.println("出现误判了~,值:"+i+"==是存在的");
        }
    }
    int count = 0;
    // 判断没有在布隆过滤器中的值是否有误判情况
    for (int i = num; i <num+num ; i++) {
        if (bloomFilter.mightContain(i)){
            count += 1;
        }
    }
    System.out.println("不存在布隆过滤器中的元素误判数量:"+count);
}
  

结果展示,存在误判情况,符合预设置的误差范围

其它命令可以参考guava官网API文档

布隆过滤器配置参考

我们可以通过github上开源工具,输入布隆过滤器大小以及可以接受的误差率,计算布隆过滤器的最佳配置,计算工具参考

错误率和哈希函数以及内存容量有关,当错误率越低,那么需要的哈希函数个数就得越多,内存容量就得越大,所以布隆过滤器的设置需要根据实际业务确定,这是在准确率和性能上做了取舍。

布隆过滤器的应用场景

布隆过滤器虽然存在误判率和删除困难的缺点,但其能快速判断对象是否存在的特性依旧应用广泛,常见用于

  • 防止Redis缓存穿透。
  • 爬虫过滤,已抓取的url不再抓取。
  • 垃圾邮件过滤等。

文章来源:智云一二三科技

文章标题:Redis实现布隆过滤器(下)

文章地址:https://www.zhihuclub.com/177010.shtml

关于作者: 智云科技

热门文章

网站地图