【C++】 ——億級數據過濾之布隆過濾器

一、布隆過濾器

秉承着學習的態度,博主對布隆過濾器產生了很大的興趣,它適用於大數據處理,比如垃圾郵件過濾,電話黑名單,URL去重,網頁黑名單等都

“寧可錯殺一千,也不放過一個”,這是布隆過濾器的特點,也就是說我們利用布隆過濾器判斷這一郵件是垃圾郵件一定就是準確的,也有可能將有效郵件判斷稱垃圾郵件,布隆過濾器存在誤判的可能。接下來,我們就來看看布隆過濾器的原理。

二、布隆過濾器的原理

在這之前,我們考慮一個問題,通常我們判斷一個數據是否在一個大的數據集合中通常採用的是什麼辦法?應該蠻多人回答HashMap,確實可以將值映射到HashMap的key中,時間複雜度是O(1),效率也挺高。我們面對下現實,當我們的數據集是40億的時候,它原本存儲在遠程服務器上,本地服務器接收輸入,我們不可能一次性將數據讀進內存構建HashTable.

我覺得布隆過濾器就是利用位圖這一原理來提高空間利用率,1個整型=4個字節=32個比特位,原來存儲一個整形數字的空間,現在使用位圖,可以存儲32個數字的標誌位,需要注意的是,位圖裏面存放的並不是key值,而是標誌位,如果key值是垃圾郵件,就將標誌位設爲1(二進制的0和1)。先開始的一種方法是我們利用一個哈希函數,讓所有的垃圾郵件都通過這一個函數映射出位置,如圖所示:
在這裏插入圖片描述
這會產生一個問題,那就是如果垃圾郵件abcd已經將該位置爲1,另一個垃圾郵件bcda來了以爲自己被標記過了,就會被誤認爲是有效郵件。這是不合理的。所以我們這裏採用多個不同的哈希函數生成多個哈希值,並對每個生成的哈希值指向的bit位置爲1.如圖所示:
在這裏插入圖片描述
abcd和三個不同的哈希函數分別生成了哈希值1,4,7,我們就將1,4,7位置置爲1,如果接下來的垃圾郵件是bcda,如圖所示:
在這裏插入圖片描述
他映射的位置是2,4,8,我們看到4這個位置由於兩個值的哈希函數都映射到了,因此它被覆蓋了。那如果我們現在想查詢郵件www.cabd.com是不是垃圾郵件,哈希函數分別返回1,5,8三個值,結果我們發現5這個比特位是0,說明他是有效郵件。當我們查詢www.dbca.com是不是垃圾郵件的時候,發現他經過哈希函數映射的是2,4,7這個位置,那我們是不是就能說這個郵件就是垃圾郵件了呢?不可以的,我們只能說他可能是垃圾郵件。

原因爲何?很簡單,當隨着增加的值越來越多,被置爲1的bit位也會越來越多,這樣某個值雖然沒有被存儲過,但是哈希函數返回的值已經被其他的值覆蓋成了1,程序還是會判斷www.dbca.com是垃圾郵件。這也就是說如果一個郵件是垃圾郵件,布隆過濾器一定能判斷出來,但是會存在誤判的原因。

三、布隆過濾器不支持刪除

根據以上我們知道,布隆過濾器是支持add的,但是這裏需要說明的是它不支持刪除,比如上圖中的垃圾郵件abcd和dcba映射了同一個位置4,如果abcd刪除了,將4置爲0,那下一次判斷dcba是否溼垃圾郵件的時候會直接返回false,實際上你並沒有刪除它。

如何解決這個問題?答案是計數刪除。但是計數刪除需要存儲一個數值,而不是原來的bit位,會增大佔用內存的大小,這樣的話,增加一個值就是將對應索引槽上存儲的值加1,刪除則是減1,判斷是否存在則是看值是否大於0.

四、布隆過濾器的使用場景

場景一:使用布隆過濾器標記垃圾郵箱

理想狀態如果我們布隆過濾器已經幫我們標記了所有垃圾郵箱,那麼我們收件箱中的郵件一定是非垃圾的,但是由於會出現誤判,所以我們垃圾箱中卻可能出現非垃圾郵件
場景二:使用布隆過濾器幫助我們標記垃圾網站

理想狀態如果我們布隆過濾器已經幫我們標記了所有垃圾網站,那麼我們訪問的網站未彈出威脅信息,那麼這個網站一定是安全的,如果彈出威脅信息,因爲存在誤判,所以這個網站可能是安全的
場景三:使用布隆過濾器標記空查詢

理想狀態如果我們布隆過濾器已經幫我們標記了所有查詢,那麼如果我們進行查詢時如果這條數據不在數據庫中就直接返回,如果誤判爲在的話,我們再進行數據庫中的查找,若不在則返回。

(博主看了其他優秀文章後覺得收穫很多,布隆過濾器還挺有意思的,有問題的希望小夥伴們提出來,博主一定虛心改正)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章