bloom filter
是由bloom
在1970
年提出的一種多雜湊函式對映的快速查詢演算法。通常應用在一些需要快速判斷某個元素是否屬於集合,但是並不嚴格要求
100%
正確的場合。
一.例項
為了說明
bloom filter
存在的重要意義,舉乙個例項:
假設要你寫乙個網路蜘蛛(
web crawler
)。由於網路間的鏈結錯綜複雜,蜘蛛在網路間爬行很可能會形成「環
」。為了避免形成「環
」,就需要知道蜘蛛已經訪問過那些
url。給乙個
url,怎樣知道蜘蛛是否已經訪問過呢?稍微想想,就會有如下幾種方案:
1. 將訪問過的
url儲存到資料庫。
2. 用hashset
將訪問過的
url儲存起來。那只需接近
o(1)
的代價就可以查到乙個
url是否被訪問過了。
3. url
經過md5
或sha-1
等單向雜湊後再儲存到
hashset
或資料庫。
4. bit-map
方法。建立乙個
bitset
,將每個
url經過乙個雜湊函式對映到某一位。 方法
1~3都是將訪問過的
url完整儲存,方法
4則只標記
url的乙個對映位。
以上方法在資料量較小的情況下都能完美解決問題,但是當資料量變得非常龐大時問題就來了。 方法
1的缺點:資料量變得非常龐大後關係型資料庫查詢的效率會變得很低。而且每來乙個
url就啟動一次資料庫查詢是不是太小題大做了? 方法
2的缺點:太消耗記憶體。隨著
url的增多,占用的記憶體會越來越多。就算只有1億個
url,每個
url只算
50個字元,就需要
5gb記憶體。 方法
3:由於字串經過
md5處理後的資訊摘要長度只有
128bit
,sha-1
處理後也只有
160bit
,因此方法
3比方法
2節省了好幾倍的記憶體。 方法
4消耗記憶體是相對較少的,但缺點是單一雜湊函式發生衝突的概率太高。還記得資料結構課上學過的
hash
表衝突的各種解決方法麼?若要降低衝突發生的概率到
1%,就要將
bitset
的長度設定為
url個數的
100倍。
二. bloom filter的演算法
廢話說到這裡,下面引入本篇的主角
——bloom filter
。其實上面方法
4的思想已經很接近
bloom filter
了。方法四的致命缺點是衝突概率高,為了降低衝突的概念,
bloom filter
使用了多個雜湊函式,而不是乙個。
bloom filter
演算法如下:
建立乙個m位
bitset
,先將所有位初始化為
0,然後選擇
k個不同的雜湊函式。第
i個雜湊函式對字串
str雜湊的結果記為h(
i,str),且h(
i,str)的範圍是0到
m-1 。
(1)加入字串過程
下面是每個字串處理的過程,首先是將字串
str「記錄」
到bitset
中的過程:
對於字串
str,分別計算h(
1,str),h(
2,str)
……h(k,
str)。然後將
bitset的第h
(1,str)、h
(2,str
)……h(k
,str
)位設為1。
1.bloom filter
加入字串過程
很簡單吧?這樣就將字串
str對映到
bitset中的k
個二進位制位了。
(2)檢查字串是否存在的過程
下面是檢查字串
str是否被
bitset
記錄過的過程:
對於字串
str,分別計算h(
1,str),h(
2,str)
……h(k,
str)。然後檢查
bitset的第h
(1,str)、h
(2,str
)……h(k
,str
)位是否為
1,若其中任何一位不為
1則可以判定
str一定沒有被記錄過。若全部位都是1,則
「認為」字串
str存在。
若乙個字串對應的
bit不全為
1,則可以肯定該字串一定沒有被
bloom filter
記錄過。(這是顯然的,因為字串被記錄過,其對應的二進位制位肯定全部被設為1了)
但是若乙個字串對應的
bit全為
1,實際上是不能
100%
的肯定該字串被
bloom filter
記錄過的。(因為有可能該字串的所有位都剛好是被其他字串所對應)這種將該字串劃分錯的情況,稱為
false positive 。
(3)刪除字串過程
字串加入了就被不能刪除了,因為刪除會影響到其他字串。實在需要刪除字串的可以使用
counting bloom filter(cbf)
,這是一種基本
bloom filter
的變體,
cbf將基本
bloom filter
每乙個bit
改為乙個計數器,這樣就可以實現刪除字串的功能了。
bloom filter
跟單雜湊函式
bit-map
不同之處在於:
bloom filter
使用了k
個雜湊函式,每個字串跟k個
bit對應。從而降低了衝突的概率。
三. bloom filter引數選擇
(1)雜湊函式選擇
雜湊函式的選擇對效能的影響應該是很大的,乙個好的雜湊函式要能近似等概率的將字串對映到各個
bit。選擇
k個不同的雜湊函式比較麻煩,一種簡單的方法是選擇乙個雜湊函式,然後送入
k個不同的引數。
(2)bit陣列大小選擇
雜湊函式個數
k、位陣列大小
m、加入的字串數量
n的關係可以參考參考文獻
1。該文獻證明了對於給定的m、
n,當k = ln(2) * m/n
時出錯的概率是最小的。
同時該文獻還給出特定的k,
m,n1
,雜湊函式個數k取
10,位陣列大小
m設為字串個數n的
20倍時,
false positive
發生的概率是
0.0000889
,這個概率基本能滿足網路爬蟲的需求了。
BloomFilter 大規模資料處理利器
bloom filter是由bloom在1970年提出的一種多雜湊函式對映的快速查詢演算法。通常應用在一些需要快速判斷某個元素是否屬於集合,但是並不嚴格要求100 正確的場合。一.例項 為了說明bloom filter存在的重要意義,舉乙個例項 假設要你寫乙個網路蜘蛛 web crawler 由於網...
大規模資料實戰
前後端處理分離解耦,前批處理 有向圖編譯,後端為有向圖優化 自動資源分配 自動監控 錯誤跟蹤 首先我們忘掉所有的框架,我們想做的業務設計其實是就是乙個count 乙個topk 衡量指標很簡單是sla 工程一致性模型,強一致性,弱一致性,最終一致性 cloud spanner 就是強一致性,業務級的資...
Python大規模資料插入Postgresql
需要owner許可權 alter table t rs standard satellite image add constraint unique source product id unique source product id batchinsert批量插入 def batchinsert ...