演算法 3 布隆過濾器原理

2022-09-23 12:09:11 字數 4094 閱讀 1705

開發乙個電商專案,因為資料量一直在增加(已達億級),所以需要重構之前開發好的秒殺功能,為了更好的支援高併發,在驗證使用者是否重複購買的環節,就考慮用布隆過濾器。

也順便更加深入的去了解下布隆過濾器的原理,感覺還是蠻有意思的,這一連串的公式不靜下心來思考,很容易被繞暈。

1、什麼是布隆過濾器

本質上布隆過濾器是一種資料結構,比較巧妙的概率型資料結構,特點是高效地插入和查詢。根據查詢結果可以用來告訴你某樣東西一定不存在或者可能存在這句話是該演算法的核心。

相比於傳統的 list、set、map 等資料結構,它更高效、占用空間更少,但是缺點是其返回的結果是概率性的,而不是確切的,同時布隆過濾器還有乙個缺陷就是

資料只能插入不能刪除

2、資料如何存入布隆過濾器

布隆過濾器是由乙個很長的bit陣列和一系列雜湊函式組成的

陣列的每個元素都只佔1bit空間,並且每個元素只能為0或1。

布隆過濾器還擁有k個雜湊函式,當乙個元素加入布隆過濾器時,會使用k個雜湊函式對其進行k次計算,得到k個雜湊值,並且根據得到的雜湊值,在維陣列中把對應下標的值置位1。

判斷某個數是否在布隆過濾器中,就對該元素進行k次雜湊計算,得到的值在位陣列中判斷每個元素是否都為1,如果每個元素都為1,就說明這個值在布隆過濾器中。

3、布隆過濾器為什麼會有誤判

當插入的元素越來越多時,當乙個不在布隆過濾器中的元素,經過同樣規則的雜湊計算之後,得到的值在位陣列中查詢,有可能這些位置因為其他的元素先被置1了。

所以布隆過濾器存在誤判的情況,但是如果布隆過濾器判斷某個元素不在布隆過濾器中,那麼這個值就一定不在

如果對布隆過濾器的概念還不是很理解的話,推薦一篇部落格,**並茂好理解很多。詳解布隆過濾器的原理、使用場景和注意事項

4、使用場景背景現在有個100億個黑名單網頁資料,每個網頁的url占用64位元組。現在想要實現一種網頁過濾系統,可以根據網頁的url判斷該**是否在黑名單上,請設計該系統。

需求可以允許有0.01%以下的判斷失誤率,並且使用的總空間不要超過200g。

這裡一共有4個常量:

100億條黑名單資料每條資料佔64個位元組,萬分之一的失誤率總空間不要超過200g

如果不考慮不攏過濾器,那麼這裡儲存100億條資料就需要 100億 * 64位元組 = 596g 顯然超過300g

解題在滿足有100億條資料並且允許萬分之一的失誤率的布隆過濾器需要多大的bit陣列呢?

布隆過濾器的大小m公式

求得 m = 19.19n,向上取整為 20n。所以2000億bit,約為186g。

算完m,我們順便來算下m,n已知,這時滿足最小誤差的k是幾個。

雜湊函式的個數k公式

求得 k = 14,即需要14個雜湊函式。

通過通過 m = 20n, k = 14我們再來算下真實的失誤率。

布隆過濾器真實失誤率p公式

求得 p = 0.006%,即布隆過濾器的真實失誤率為0.006%。

通過布隆過濾器公式也可以看出:

單個資料的大小不影響布隆過濾器大小,因為樣本會通過雜湊函式得到輸出值

就好比上面的每個網頁的url占用64位元組這個資料大小 跟布隆過濾器大小沒啥關係。

這三個公式就是有關布隆過濾器已經推倒出的公式,下面我們來推下這個公式是如何推導出來的。

講公式,應該先知道幾個關鍵的常量。

誤判率p布隆過濾器長度m元素個數n雜湊函式個數k

我們再來一步一步由簡單到難推導公式。

1、誤差率公式推導

前提條件:就是假設每個元素雜湊得到的值分布到m陣列上的每乙個陣列節點的概率是相等的。

1) 假設布隆過濾器長度為m,元素個數n為1,雜湊函式個數k也為1。那麼在插入時某一陣列節點沒有被置為1的概率。

這個應該很好理解。

2)如果上面其它不變,而雜湊函式個數變成k個,那麼在插入時某一陣列節點沒有被置為1的概率。

好理解!

3)如果元素個數變成n個,而雜湊函式個數變成k個,那麼在插入時某一陣列節點沒有被置為1的概率。

4)從上面推導出的是: 當布隆過濾器長度為m,元素個數變成n個,雜湊函式個數變成k個的時候,某一節點被置為1的概率為

到這裡應該也好理解,第三步是該位置從未被置為1,那麼1去減去它就是至少有一次被置為1,那麼只要存在一次被置1,那麼該位置的bit標示就是1,因為布隆過濾器是不能刪除的。

5)這個還需要考慮到,乙個元素通過hash會生成多個k,放入m陣列中,所以需要這k個值都為1才會認為該該元素已經存在。所以是這樣的。

上面這個公式推導在轉換下就成了

思考為什麼上面這個公式的值就是最終的誤差率?

因為當乙個布隆過濾器中不存在的元素進來的是的時候,首先通過hash演算法產生k個雜湊值,分布在m陣列上都為1的的概率不就是上面推導出的這個公式嗎,那不就是誤差嗎?

因為明明是不存在的值,卻有這個概率表明已經存在。

思考給定的m和n,思考k值為多少誤差會最小

為什麼k值的大小不合理會影響誤差呢?

我們來思考下,乙個元素最終生成k個hash值,那麼會在陣列m上的k個位置標記為1。

假設k為1,那麼每次進來只在m上的某乙個位置標記為1,這樣的話如果乙個新元素進來剛好hash值也在這裡,而不用其它位置來判斷是否為1,這個誤差就會比較大

假設k為m,那麼第乙個元素進來,在m上所有位置上都表為1了 ,以後只要進來乙個元素就會標記為已存在。這個誤差也太大了

上面只是舉了兩個極端的例子,但也說明k值太大、太小都不好,它的最優值一定跟m、n存在某種關係。

至於完整公式的推導,我這裡就不在寫了,後面會貼乙個人家怎麼推導的部落格。

它們之間的關係只要記住下面這個公式就可以了。

這篇部落格就到這裡了,後面有整理通過谷歌的gu**a工具 和 redis 實現布隆過濾器的示例。通過lua指令碼批量插入資料到redis布隆過濾器

演算法 布隆過濾器

面試的時候我們經常會被問到,100億個url中有多少重複的,或者讓你設計乙個100億個url的黑名單。傳統使用hash去儲存,1個url算64bit,100億個我們需要320g的記憶體來處理,就需要各種分布式各種演算法來懟,對於公司來說是一筆不小的開銷而且很慢。這個時候如果說允許有失誤,而且是 另可...

布隆過濾器

布隆過濾器 bloom filter 是1970年由布隆提出的。它實際上是乙個很長的二進位制向量和一系列隨機對映函式。布隆過濾器可以用於檢索乙個元素是否在乙個集合中。它的優點是空間效率和查詢時間都遠遠超過一般的演算法,缺點是有一定的誤識別率和刪除困難。如果想要判斷乙個元素是不是在乙個集合裡,一般想到...

布隆過濾器

布隆過濾器的概念 如果想要判斷乙個元素是不是在乙個集合裡,一般想到的是將所有元素儲存起來,然後通過比較確定。鍊錶,樹等等資料結構都是這種思路.但是隨著集合中元素的增加,我們需要的儲存空間越來越大,檢索速度也越來越慢 o n o logn 不過世界上還有一種叫作雜湊表 又叫 雜湊表,hash tabl...