布隆过滤器

大数据量的存储、筛选、重排等背景下产生的优秀算法。
在大数据量下,应用程序,会出现很多空间,时间的问题。常用的思想就是:将每条数据通过一定的算法转变成占存更小的ID(指纹),通过对指纹的存储和计算来对整个数据量级的减少。(合理的运用容器,指纹之间也可以通过分段的方式共用相同的存储块)

布隆过滤器的的着重点是过滤,不关心具体的业务内容。适用场景:计算一个url在一个url集(大数据量)中是否存在爬虫访问记录。
步骤解析
“通过一定的算法转变成占存更小的ID(指纹)”:Hash算法可以支持(用Hash就要容忍Hash的弊端:Hash冲突,幸运的是一般用到布隆过滤器的场景都需要那么精确)
“指纹的存储和计算来对整个数据量级的减少”:指纹映射到一个大的按位存储的空间中(指纹之间也可以通过分段的方式共用相同的存储块)

优点:空间和时间效率都很高。 缺点:随着存入的元素数量增加,误算率(HASH)随之增加。

具体实现
“Hash算法可以支持”,但一个hash函数的冲突率会很大,可以原值通过N个Hash算法得到N个数字,将N个数字对应在“按位存储的空间中”(bitMap,int[])下标的值变为1.具体实现看开发者。
这样就完成了数据的“转变存储”,判断一个值存不存在,通过对应算法算出N个数字,去bitMap中看每个下标对应的值是否都是1即可。
当然有误判率。

注意点
““按位存储的空间中”(bitMap,int[])” 中位数如何限定?
过小的布隆过滤器很快所有的 bit 位均为 1。布隆过滤器的长度会直接影响误报率,布隆过滤器越长其误报率越小。
“N个Hash算法”,N怎么取?
个数越多则布隆过滤器 bit 位置位 1 的速度越快,且布隆过滤器的效率越低;但是如果太少的话,那我们的误报率会变高。
假设 Hash 函数以等概率条件选择并设置 Bit Array 中的某一位,m 是该位数组的大小,k 是 Hash 函数的个数。

而对于给定的False Positives概率 p,如何选择最优的位数组大小 m 呢,
在这里插入图片描述
上式表明,位数组的大小最好与插入元素的个数成线性关系,对于给定的 m,n,k,假正例概率最大为:
在这里插入图片描述
摘自:https://www.cnblogs.com/bonelee/p/6215176.html

java代码j简单示例

public class BloomFilter<T> {

    //bit容器
    private byte[] bitMap;

    //容器长度
    private int BIT_MAP_LENGTH;

    //hash个数
    private int HASH_NUM;

    public BloomFilter(int BIT_MAP_LENGTH, int HASH_NUM) {
        this.bitMap = new byte[BIT_MAP_LENGTH];
        this.BIT_MAP_LENGTH = BIT_MAP_LENGTH;
        this.HASH_NUM = HASH_NUM;
    }

    private int[] getHash(T value) {
        int[] result = new int[HASH_NUM];
        Stream.iterate(0, i -> i + 1).limit(HASH_NUM).forEach(i -> result[i] = (value.toString() + i).hashCode() % BIT_MAP_LENGTH);
        return result;
    }

    public boolean isContain(T value) {
        for (int hash : getHash(value)) {
            if (bitMap[hash] != 1) {
                return false;
            }
        }
        return true;
    }

    public void add(T value) {
        for (int hash : getHash(value)) {
            bitMap[hash] = 1;
        }
    }

    public static void main(String[] args) {
        BloomFilter bloomFilter = new BloomFilter<String>(1024, 8);
        Stream.iterate(1, i -> i + 1).limit(1024).forEach(i -> bloomFilter.add(i));
        System.out.println(bloomFilter.isContain(1));
        System.out.println(bloomFilter.isContain(10000000));
    }
}

分布式系统中,可基于redis的bitMap作为容器来实现。原理一样。

布隆过滤器有很多致命软肋,有人推布谷鸟过滤器
https://zhuanlan.zhihu.com/p/68418134
主要还是看场景吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值