布隆过滤器

   布隆过滤器的由来

   布隆过滤器为啥不叫艾希过滤器?不叫丽桑卓过滤器?
   因为它是1970年由一个叫布隆的大佬设计的,就像如果是我设计的,那就叫番茄过滤器。

   布隆过滤器简介

   布隆过滤器实际上是一个很长的二进制向量(可以理解为就是个数组)和一系列随机映射函数(hash函数)。布隆过滤器可以用于检索一个元素是否存在。它的优点是空间效率和查询时间都比一般的算法要好的多,并且占用空间小,缺点是有一定的误识别率和删除困难。一般用于过滤请求的非法key(比如查询年龄为-1的人),缓解缓存的击穿问题。

   布隆过滤器能解决啥问题

   明人不说暗话,这玩意就是用来解决缓存穿透的,就是当有些数据库中不存在的数据被用户请求访问,一开始去redis里查询,肯定是查不到,数据库里都没有缓存里咋可能有,这时这些请求就会直接进入数据库中,数据库中也没有,于是本次查询失败,这种情况一次两次还行,次数多了数据库遭不住,布隆过滤器就是用来缓解这个情况的。

   布隆过滤器工作原理

   布隆过滤器会把每个已有的数据进行若干个不同的hash运算(可以自定义)得到一个key,然后根据这个key去修改自己数组里的对应下标的值(从0改成1),查询的时候直接把请求中的key进行hash运算后去查看数组中对应下标的值是否为1,如果为1,则说明这个数据可能存在,如果出现了0,那这个数据就肯定不存在,为什么?

   看我举一个栗子

例:

   现在有两个元素a和b,通过计算得出

   a的key为[0,3,5]

   b的key为[3,5]

   布隆过滤器的初始数组为[0,0,0,0,0,0,0,0]

   此时数据库中写入a元素,布隆过滤器会对其进行记录

   记录后的数组为[1,0,0,1,0,1,0,0,0]

   这时进来一个请求要查询b,b的key通过运算得出为3和5,在布隆过滤器中查询结果全为1,但是数据库中是没有b这个数据的,这就是为啥即使全为1数据也不一定存在的理由。虽然布隆过滤器存在误判率,但是肯定利大于弊的(总比被穿透好撒)。

   贴个Demo(不是我写的)

   代码来自一位不愿意透露姓名的靓仔->靓仔的主页
   如果对hash算法有啥疑惑的点这->帮你真正理解hashCode和hash算法

public class MyBloomFilter {
    //你的布隆过滤器容量
    private static final int DEFAULT_SIZE = 2 << 28;
    //bit数组,用来存放key
    private static BitSet bitSet = new BitSet(DEFAULT_SIZE);
    //后面hash函数会用到,用来生成不同的hash值,可随意设置,别问我为什么这么多8,图个吉利
    private static final int[] ints = {1, 6, 16, 38, 58, 68};

    //add方法,计算出key的hash值,并将对应下标置为true
    public void add(Object key) {
        Arrays.stream(ints).forEach(i -> bitSet.set(hash(key, i)));
    }

    //判断key是否存在,true不一定说明key存在,但是false一定说明不存在
    public boolean isContain(Object key) {
         boolean result = true;
        for (int i : ints) {
        	//短路与,只要有一个bit位为false,则返回false
            result = result && bitSet.get(hash(key, i));
        }
        return result;
    }

    //hash函数,借鉴了hashmap的扰动算法,强烈建议大家把这个hash算法看懂,这个设计真的牛皮加闪电
    private int hash(Object key, int i) {
        int h;
        return key == null ? 0 : (i * (DEFAULT_SIZE - 1) & ((h = key.hashCode()) ^ (h >>> 16)));
    }
}

   测试

   public static void main(String[] args) {
        MyNewBloomFilter myNewBloomFilter = new MyNewBloomFilter();
        myNewBloomFilter.add("张学友");
        myNewBloomFilter.add("郭德纲");
        myNewBloomFilter.add("蔡徐鸡");
        myNewBloomFilter.add(666);
        System.out.println(myNewBloomFilter.isContain("张学友"));//true
        System.out.println(myNewBloomFilter.isContain("张学友 "));//false
        System.out.println(myNewBloomFilter.isContain("张学友1"));//false
        System.out.println(myNewBloomFilter.isContain("郭德纲"));//true
        System.out.println(myNewBloomFilter.isContain("蔡徐老母鸡"));//false
        System.out.println(myNewBloomFilter.isContain(666));//true
        System.out.println(myNewBloomFilter.isContain(888));//false
    }

   插一嘴

   这里介绍一下布隆过滤器的升级版(升了但只能升一点点)——布谷鸟过滤器
   布谷鸟过滤器有两张hash表,两个表的hash函数也不一样,当有数据进来后,会分别算出两个表中对应的位置,然后尝试放入其中一个表,如果表中对应位置为空,则放入成功,如果该表位置已经有数据抢占了,就去尝试放入另一张表。当然,最后肯定还是会出现问题,当一个数据两张表的位置都被占了,这代表布谷鸟过滤器的hash算法达到了性能瓶颈,此时需要对哈希算法进行性能优化。总的来说布谷鸟过滤器在错误率小于3%的时候空间性能是优于布隆过滤器的,而这个条件在实际应用中常常满足,所以一般来说它的空间性能是要优于布隆过滤器的。
   

内容参考:布谷鸟过滤器
   
   

PS:所有的内容都是我自己的理解,肯定有不对的地方,欢迎指正。
   

OK  我发言完毕  bye~

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值