微服务解决方案 -- BloomFilter 布隆过滤器 (外传二)

布隆过滤器

场景分析


在这里插入图片描述
如何解决这个问题,这个时候会想到布隆过滤器,有用redis的,也有用guava的,还有自己实现的。

首先布隆过滤器是一个bit向量或数组,这里就当做数组了。

我们得初始化这个数组即给与这个过滤器一定的长度,然后我们对一个key进行hash算法,可以多次hash,下图就hash了3次,将数组的对应的index的值设置为1。

在这里插入图片描述
完成了以后当该key再次请求过来的时候将三次hash的结果进行与运算,如果结果为1时就说明我们的这个key存在,即可以继续请求缓存或者数据库,如果为0就直接返回。如果一个keyhash结果与其他keyhash结果有冲突的话,就出现误判的情况。

// 假设我的bloomFilter算法用的是String的hashCode()的方法,就会出现哈希碰撞
 @Test
  public void testVoid(){
    
    
      System.out.println("Ea".hashCode());
      System.out.println("FB".hashCode());
  }
// 打印结果
// 2236
// 2236

这就是 否一定为否,真不一定为真在这里插入图片描述

实现


关于BloomFilter的实现也有很多,我们就用最简单的guava

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>25.1-jre</version>
</dependency>
@Test
    public void bloomFilter(){
    
    
        // 指定过滤器的大小
        int size = 100000;
        // 误差率
        double fpp = 0.001;
        BloomFilter<String> bloomFilter = BloomFilter.create(Funnels.stringFunnel(Charset.forName("utf-8")), size, fpp);
        // 将过滤器存满数据,当数据<1000000时 一定存在,大于1000000 理论上不存在,但是存在误判
        for (int i = 0; i < 100000 ; i++) {
    
    
            bloomFilter.put(""+i);
        }

        int count = 0;
        // 取100000以上的数字 执行1000000次 存在一次 计数器+1
        for (int j = 100000; j < 200000 ; j++) {
    
    
            if (bloomFilter.test(""+j)){
    
    
                count++;
            }
        }
        System.out.println(count/100000.0);
    }

// 打印结果
0.00112

参考资料


[布隆过滤器的误判率该如何计算?(https://www.zhihu.com/question/38573286)]

[布隆过滤器(Bloom Filter) 未完待续 (https://www.cnblogs.com/noKing/p/9352377.html)]

[大白话布隆过滤器(https://www.cnblogs.com/CodeBear/p/10911177.html)]

猜你喜欢

转载自blog.csdn.net/weixin_42126468/article/details/106163501