代码-布隆过滤器

    科技2024-11-19  20

    一、作用

    用来判断海量数据中是否存在指定值。

    二、原理

    将容器中的所有值求hashcode然后根据hashcode找,类似于hashmap,但不同的是这里只比较hash值,没有hash值相同之后的进一步精确匹配。 所以出现hash碰撞时,不能确定是否真的存在,此时可以使用不同的hash算法对数组中元素设置多个值,然后对每个值进行匹配。所以只要算法够多,误判几率就越低。

    三、应用场景

    Hbase就使用布隆过滤器来找rowkey,也会有误判的情况,本来没有,但返回有,此时无非就是遍历一个hfile而已,白搜了一个文件。可以接受。 新老用户判断 爬虫

    四、使用

    1. Hbase使用的是guava中的api

    BloomFilter也是相当于一个容器,只不过这个容器里会对放入的元素求多个hashcode,然后把这些hashcode作为这个元素的下标。所以使用BloomFilter时,先创建BloomFilter对象,然后把元素put进去。然后就可以使用mightContain()判断是否存在了。

    scala代码中一定要注意,BloomFilter.create[String]要加泛型,不然会报trying to do lub/glb of typevar ?Thttps://stackoverflow.com/questions/40585069/guava-bloomfilter-error-in-scala-compiler-trying-to-do-lub-glb-of-typevar-t

    import com.google.common.base.Charsets import com.google.common.hash.{BloomFilter, Funnels} object 布隆过滤器 { def main(args: Array[String]): Unit = { // 样本 val arr: Array[String] = Array("asdf", "qw", "qwe", "qwer", "aa", "zxc", "zz", "bb") // 创建bloomFilter,类型、可能的数据量(必须比实际数据量大,但一般都是实际量的10倍以上)、误判几率 val bloomFilter: BloomFilter[String] = BloomFilter.create[String](Funnels.stringFunnel(Charsets.UTF_8), 100000, 0.000001) // 将样本中元素put到bloomFilter arr.foreach(bloomFilter.put(_)) // 判断指定元素是否存在 println(bloomFilter.mightContain("qw")) println(bloomFilter.mightContain("123")) } }

    2. 使用hadoop中的布隆过滤器工具类,这个不需要额外导包,sparksql的包中就有,core没有

    object hadoop布隆过滤器 { def main(args: Array[String]): Unit = { // 样本 val arr: Array[String] = Array("asdf", "qw", "qwe", "qwer", "aa", "zxc", "zz", "bb") val bloomFilter = new BloomFilter(100000,4,1) arr.foreach(ele => bloomFilter.add(new Key(ele.getBytes()))) println(bloomFilter.membershipTest(new Key("qw".getBytes()))) println(bloomFilter.membershipTest(new Key("12".getBytes()))) } }

    在spark中使用,有2个问题:

    创建bloomFilter 时,需要获取所有样本的集合,而样本的数据是分布式的,所以要么collect到driver,要么把bloomFilter 作为累加器广播出去。需要把bloomFilter 对象广播出去,而因为bloomFilter 是hadoop提供的,实现了writeable接口,没有实现serializable接口,MR可以序列化,spark不能。所以会报无法序列化的错。因为spark默认用jdk的序列化框架,而jdk序列化框架的标记就是serializable。此时,可以用spark的序列化框架kryo。当然也可以写个子类实现serializable。 ==》 使用kryo,能自动将driver中的共享变量序列化
    Processed: 0.010, SQL: 8