布隆过滤器

简介: 布隆过滤器
2.1 布隆过滤器的概念

布隆过滤器的底层数据结构与位图相同,且具备一系列哈希函数,可以做到快速查询一个元素是否在集合中,同时节省内存空间。

它的缺点是 存在误判(原本不存在,判断为存在)不便删除

可以把布隆过滤器想象成一个集合,Set() 插入元素,Test() 元素是否存在。

  • Set("Tencent") ——> 经过一系列哈希函数的映射,对布隆过滤器底层数据结构上 pos1、pos2、... 等位置进行标记;
  • Test("Tencent") ——> 判断Tencent经这一系列哈希函数映射的、对应底层数据结构的位置,是否都被标记,得出结论。
  • 存在误判:若插入一系列元素,经一系列哈希函数映射,分别标记 Tencent 所对应的 pos1、pos2、... ,那么即便没有插入 “Tencent” ,Test(Tencent)的结果仍然为 True ;可以通过 扩大底层空间增加哈希函数个数 减小误判率。
  • 不便删除:删除 “Tencent”是否意味着要将其映射的位置重新标记成 0 ?假设 “Tencent” 与 “Baidu” 映射到同一 pos2 ,删除 “Tencent” ,将无法再查询到 “Baidu”。
2.2 性能优秀的字符串哈希算法

详细:

[各种字符串 Hash 函数]  https://www.cnblogs.com/-clq/archive/2012/05/31/2528153.html 

    struct HashFuncBKDR
    {    
        // BKDR
        size_t operator()(const string& s)
        {
            size_t hash = 0;
            for (auto ch : s)
            {
                hash *= 131;
                hash += ch;
            }
            return hash;
        }
    };
    struct HashFuncAP
    {
        // AP
        size_t operator()(const string& s)
        {
            size_t hash = 0;
            for (size_t i = 0; i < s.size(); i++)
            {
                if ((i & 1) == 0) // 偶数位字符
                {
                    hash ^= ((hash << 7) ^ (s[i]) ^ (hash >> 3));
                }
                else              // 奇数位字符
                {
                    hash ^= (~((hash << 11) ^ (s[i]) ^ (hash >> 5)));
                }
            }
            return hash;
        }
    };
    struct HashFuncDJB
    {
        // DJB
        size_t operator()(const string& s)
        {
            size_t hash = 5381;
            for (auto ch : s)
            {
                hash = hash * 33 ^ ch;
            }
            return hash;
        }
    };
2.3 BloomFilter 实现
    template<size_t N, class K = string
        class Hash1 = HashFuncBKDR,
        class Hash2 = HashFuncAP,
        class Hash3 = HashFuncDJB>
    class BloomFilter
    {
    private:
        static const size_t M = 5 * N; // 静态成员常量,用于给底层开更大的空间
        // 2 种创建底层的写法
        bitset<M> _bs; // 1
        bitset<M>* _bs = new bitset<M>; // 2
    };

经过实测,std::bitset 是在栈区开空间,当数据量很大时会导致栈溢出,因此选择第二种写法 —— 在堆区开空间:

       bitset<M>* _bs = new bitset<M>;

不需要为 BloomFilter 写构造函数, bitset 会调用自己的构造函数。

    class BloomFilter
    {
    public:
        void Set(const K& key)
        {
            size_t Hashi1 = Hash1()(key) % M; // 仿函数;% M 防止越界访问
            size_t Hashi2 = Hash2()(key) % M;
            size_t Hashi3 = Hash3()(key) % M;
            
            _bs->set(Hashi1);
            _bs->set(Hashi2);
            _bs->set(Hashi3);
        }
        
        bool Test(const K& key)
        {
            size_t Hashi1 = Hash1()(key) % M;
            if (_bs->test(Hashi1) == false)
                return false;
            
            size_t Hashi2 = Hash2()(key) % M;
            if (_bs->test(Hashi2) == false)
                return false;
            
            size_t Hashi3 = Hash3()(key) % M;
            if (_bs->test(Hashi3) == false)
                return false;
            
            return true;
        }
    };
2.4 切分思想
  1. 给一个超过100G大小的log file, log中存着IP地址, 设计算法找到出现次数最多的IP地址?
  2. 给两个文件,分别有100亿个query,我们只有1G内存,如何找到两个文件交集?

处理这类大量数据的问题,通用的解法就是:把大文件按照某种规律分为若干个小文件存进硬盘中,如: Hash(IP) % 1000Hash(query) % 1000 —— 通过哈希函数把具有相同特征的元素分成 1000 份,再在内存中对这些小文件逐个处理

某个小文件太大,分为两种情况:

  1. 存在大量重复的元素。 ——> 存入 set 或 bitset 等容器中,会自动去重,无须担心。
  2. 存在大量不重复的元素。——> 换一个哈希函数,把该小文件再切分,再处理,以此类推。
2.5 拓展支持删除

以多个比特位组为一个标准单位。

相关文章
|
4月前
|
存储 缓存 NoSQL
详解布隆过滤器原理与实现
详解布隆过滤器原理与实现
|
6月前
|
算法 Java 索引
布隆过滤器
这里假设没有字符串对应所有的hash算法与第二个字符串的第二个hash算法的的值相同。则第二个字符串第二个hash算法对应的bit位是0,所以这时,布隆过滤器会判定第二个字符串是不存在的。这个与我们实际的期望相符。
60 0
|
7月前
|
算法 NoSQL Redis
一文搞懂布隆过滤器(BloomFilter)
一文搞懂布隆过滤器(BloomFilter)
369 0
|
7月前
|
存储 数据采集 缓存
解密布隆过滤器:数据领域的魔法阵
解密布隆过滤器:数据领域的魔法阵
105 0
|
7月前
|
存储 NoSQL Java
什么是布隆过滤器?如何实现布隆过滤器?
什么是布隆过滤器?如何实现布隆过滤器?
132 0
|
存储 数据采集 缓存
布隆过滤器:原理与应用
在日常生活和工作中,我们经常需要处理海量的数据,筛选出有用的信息。这个时候,布隆过滤器(Bloom Filter)就派上了用场。
189 1
布隆过滤器:原理与应用
|
7月前
|
存储 算法 Linux
C++ 哈希的应用【布隆过滤器】
C++ 哈希的应用【布隆过滤器】
73 0
|
存储 算法 数据库
哈希的应用:布隆过滤器(C++实现)
哈希的应用:布隆过滤器(C++实现)
89 0
|
存储 数据采集 自然语言处理
浅析布隆过滤器
布隆过滤器 (Bloom Filter) 是 1970 年由布隆提出的。它可以检索一个元素是否存在于集合中。它的优点是空间效率高,查询时间极快,缺点是有一定的误判率,而且删除困难。
174 0
|
存储 人工智能 算法
哈希的应用——布隆过滤器
布隆过滤器是由布隆(Burton Howard Bloom)在1970年提出的 一种紧凑型的、比较巧妙的概率型数据结构,特点是高效地插入和查询,可以用来告诉你 “某样东西一定不存在或者可能存在”,它是用多个哈希函数,将一个数据映射到位图结构中。此种方式不仅可以提升查询效率,也可以节省大量的内存空间。