初識BloomFilter--布隆過濾器以及Python簡單代碼實現


用法及優缺點

BloomFilter可以解決的問題:

1.字處理軟件中,需要檢查一個英語單詞是否拼寫正確
2.在 FBI,一個嫌疑人的名字是否已經在嫌疑名單上
3.在網絡爬蟲里,一個網址是否被訪問過
4.yahoo, gmail等郵箱垃圾郵件過濾功能
5.可以用來防止緩存擊穿

算法優缺點

算法優點:
數據空間小,不用存儲數據本身。

算法本身缺點:
匹配失敗能確定“絕對不在集合中”,並不能保證匹配成功的值已經在集合中。
元素可以添加到集合中,但不能被刪除。
當集合快滿時,即接近預估最大容量時,誤報的概率會變大。
數據占用空間放大。一般來說,對於1%的誤報概率,每個元素少於10比特,與集合中的元素的大小或數量無關。 查詢過程變慢,hash函數增多,導致每次匹配過程,需要查找多個位(hash個數)來確認是否存在。

原理介紹

基本原理

布隆過濾器是一個判斷集合中是否包含特定元素的算法,他無需存儲數據本身。
布隆過濾器(Bloom Filter)的核心實現是一個超大的位數組和幾個哈希函數。

假設位數組的長度為m,哈希函數的個數為k,首先將位數組進行初始化,將里面每個位都設置位0。
通過哈希將輸入的字符串映射到數據的下標,然后把下標對應的值置為1,第二次相同字符串進行計算時也會被哈希函數映射到相同的下標 則可以判斷匹配內容是否已經存在。

image.png

以上圖為例,具體的操作流程:假設集合里面有3個元素{x, y, z},哈希函數的個數為3。對於集合里面的每一個元素,將元素依次通過3個哈希函數進行映射,每次映射都會產生一個哈希值,這個值對應位數組上面的一個點,然后將位數組對應的位置標記為1。查詢W元素是否存在集合中的時候,同樣的方法將W通過哈希映射到位數組上的3個點。如果3個點的其中有一個點不為1,則可以判斷該元素一定不存在集合中。反之,如果3個點都為1,則該元素可能存在集合中。注意:此處不能判斷該元素是否一定存在集合中,可能存在一定的誤判率。可以從圖中可以看到:假設某個元素通過映射對應下標為4,5,6這3個點。雖然這3個點都為1,但是很明顯這3個點是不同元素經過哈希得到的位置,因此這種情況說明元素雖然不在集合中,也可能對應的都是1,這是誤判率存在的原因。

python簡單實例實現

如下僅為python代碼實現的BloomFilter實例。真正的BloomFilter實現需要根據初始化的位數組長度決定哈希函數的個數,也有一個復雜的hash過程。

#_*_coding:utf_8_
import BitVector
import os
import sys
 
class SimpleHash():  
    
    def __init__(self, cap, seed):
        self.cap = cap
        self.seed = seed
    
    def hash(self, value):
        ret = 0
        for i in range(len(value)):
            #加權求和
            ret += self.seed*ret + ord(value[i])
        #位運算保證最后的值在0到self.cap之間
        return (self.cap-1) & ret    
 
class BloomFilter():
    
    def __init__(self, BIT_SIZE=1<<25):
        self.BIT_SIZE = 1 << 25
        self.seeds = [5, 7, 11, 13, 31, 37, 61]
        self.bitset = BitVector.BitVector(size=self.BIT_SIZE)
        self.hashFunc = []
        
        for i in range(len(self.seeds)):
            self.hashFunc.append(SimpleHash(self.BIT_SIZE, self.seeds[i]))
        print(self.hashFunc)
        
    def insert(self, value):
        for f in self.hashFunc:
            loc = f.hash(value)
            self.bitset[loc] = 1
        print(self.bitset)

    def is_contaions(self, value):
        if value == None:
            return False
        ret = True
        for f in self.hashFunc:
            loc = f.hash(value)
            ret = ret & self.bitset[loc]
        return ret

文章內容部分引用:
布隆過濾器實戰【防止緩存擊穿】
http://blog.itpub.net/31561269/viewspace-2639083/
詳解,包括錯誤率計算
https://blog.csdn.net/liangbopirates/article/details/8741367

https://blog.csdn.net/demon24/article/details/8537665


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM