13-布隆过滤器

nobility 发布于 2022-11-12 1960 次阅读


布隆过滤器

  • 普通过滤器
    • 若数据集是有一定范围,则可以制定判断是否在该范围内(bitMap标记、大小于号范围判定),从而判定是否在数据集中,bitMap标记性能差,大小与号编程复杂
    • 若数据集是非数字,将所有数据的某个属性都放在一个集合中(hyperloglog、set、list)中,若集合中有则说明该元素包含在在数据集中,hyperloglog有一定不可控的误差,其他性能差、内存开销大
  • 布隆过滤器:利用极少内存,快速的判断是否在数据集中,有一定可控的错误率,但是能保证在数据集中的数据一定能准确判定出在,不再数据集中的数据不一定准确判定出是否在(存在哈希碰撞)

原理

布隆过滤器

实现思路

过滤器存储位置 思路 优点 缺点
本地(程序内) 使用BitSet类进行位操作 速度快 容量受限,多应用过滤器同步问题
单机Redis 基于bitmap实现,利用pipeline、setbit、getbit命令实现 解决了多应用过滤器同步问题 速度较慢,容量受限512MB
集群Redis 将单个超大的过滤器分片成多个bitmap实现 解决容量受限问题 速度较慢,编码复杂

工具类中的过滤器

使用谷歌的工具类中的过滤器,仅是本地过滤器,需要引入相关jar包,需要引入相关jar包,从maven官网中查找Guava并下载

static class Person {
  int id;
  String name;

  public Person(int id, String name) {
    this.id = id;
    this.name = name;
  }
}

public static void main(String[] args) {
  /**
   *第一个参数是Funnel接口的实例:
   *    非复合类型可以直接使用Funnels静态方法中获取提供好的Funnel接口实例
   *      比如:Funnels.stringFunnel(Charset.defaultCharset)  //字符串需指定字符编码
   *    复合类型需要手动实现这个接口,并重写funnel()方法
   *      作用:是将具体的对象类型分解为原生字段值
   *          第一个参数是源对象,用于拆解的原材料,即获取属性
   *          第二个参数是分解器,调用分解器的putXxx()方法进行分解
   * 第二个参数是预存的数据数量
   * 第三个参数是容忍的错误率
   */
  BloomFilter<Person> filter = BloomFilter.create(new Funnel<Person>() {
    @Override
    public void funnel(Person person, PrimitiveSink primitiveSink) {
      primitiveSink
          .putInt(person.id)
          .putString(person.name, Charset.defaultCharset());  //字符串需指定字符编码
    }
  }, 100, 0.001);  //指定预存100个,容忍错误率为0.001

  for (int i = 0; i < 100; i++) {
    filter.put(new Person(i, String.valueOf(i))); //预备数据
  }

  boolean one = filter.mightContain(new Person(-1, String.valueOf(-1)));  //查询数据
  System.out.println(one);
  boolean two = filter.mightContain(new Person(1, String.valueOf(1)));  //查询数据
  System.out.println(two);
}
此作者没有提供个人介绍
最后更新于 2022-11-12