用法及優缺點
BloomFilter可以解決的問題:
1.字處理軟件中,需要檢查一個英語單詞是否拼寫正確
2.在 FBI,一個嫌疑人的名字是否已經在嫌疑名單上
3.在網絡爬蟲里,一個網址是否被訪問過
4.yahoo, gmail等郵箱垃圾郵件過濾功能
5.可以用來防止緩存擊穿
算法優缺點
算法優點:
數據空間小,不用存儲數據本身。
算法本身缺點:
匹配失敗能確定“絕對不在集合中”,並不能保證匹配成功的值已經在集合中。
元素可以添加到集合中,但不能被刪除。
當集合快滿時,即接近預估最大容量時,誤報的概率會變大。
數據占用空間放大。一般來說,對於1%的誤報概率,每個元素少於10比特,與集合中的元素的大小或數量無關。 查詢過程變慢,hash函數增多,導致每次匹配過程,需要查找多個位(hash個數)來確認是否存在。
原理介紹
基本原理
布隆過濾器是一個判斷集合中是否包含特定元素的算法,他無需存儲數據本身。
布隆過濾器(Bloom Filter)的核心實現是一個超大的位數組和幾個哈希函數。
假設位數組的長度為m,哈希函數的個數為k,首先將位數組進行初始化,將里面每個位都設置位0。
通過哈希將輸入的字符串映射到數據的下標,然后把下標對應的值置為1,第二次相同字符串進行計算時也會被哈希函數映射到相同的下標 則可以判斷匹配內容是否已經存在。
以上圖為例,具體的操作流程:假設集合里面有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