布隆過濾器的原理及應用

王若伊_恩賜解脫發表於2021-08-12

布隆過濾器是1970年由布隆提出的。他其實是一個很長的二進位制向量外加一系列的隨機函式函式來組成。

在正式說到布隆過濾器時,我們要先聊這樣一個話題:
在解決工程類問題時,很多問題的回答並不是只有這兩種布林狀態:
是 or 否
而可能是這兩種狀態:
一定沒有 or 可能有
亦或者可能是這兩種狀態:
一定有 or 可能沒有

針對以上的背景,我們來舉這樣一個例子:
已知:
從火車站叫車到機場,12點出發,在不堵車的情況下,耗時約50分鐘
問題1,如果12點叫車出發的話,12點10分會到麼?
答:一定不會
問題2,如果12點叫車出發的話,12點50會到麼?
答:不一定會
針對於問題1,問題2的回答,對我們來說也是有幫助的,並不是說毫無用處。
比如你要給司機打電話,詢問是否到達機場,12點10分你肯定不會打電話,這樣的問題沒有意義,還可能會影響司機的駕駛,而12點50你可能就會打電話了,因為這時候大概率是已經到了。
布隆過濾器就是這樣的一種資料結構,他不像set或者map等判定是某樣東西在或者不在,
而是用來判定某樣東西在集合中:
1,一定不存在
2,可能存在
下面我們來給出一個布隆過濾器的簡單實現:

如上圖
第一步,像hashmap一樣,我們需要準備一個長度為N的桶
第二步,準備三個hash方法,他們會根據傳入物件的key,計算出一個index值
第三步,根據計算得到的3個index值,將桶上對應的位置的值設定為1
這樣一個布隆過濾器就算做好了。
如何使用呢?

如圖,我們先對物件A進行hash運算,得出3個index值,更新到桶中

接著我們可能還會新增不同的物件到桶中,像下圖這個樣子:

然後我們依次對要檢測的物件A、B、C 進行hash1(),hash2() ,hash3()的運算,再根據運算結果匹配桶中相應位置的值時候為1,從而得出下邊這張圖,

比如在桶中,

index:1 (為1)3(為1)6(為0),因此物件B一定不存在

index:1 (為1)3(為1)5(為1),因此A物件可能存在

這樣做對我們實際業務有什麼用呢?換句話說布隆過濾器有什麼應用場景呢?
在回答這個問題之前,我們要首先明確一點,布隆過濾器不是業務資料的快取,只是一個用來判斷資料不存在性的快取,
所以我們才將其稱為布隆過濾器,而不是布隆快取。
因此我們可以將其作為一個後期需要複雜操作的一個前置過濾判斷,如:
1、底層的查詢邏輯非常複雜,而且效能低下,可以通過布隆過濾器先過濾掉一批請求,降低後臺壓力。
2、 白名單安全校驗:如果過濾器中判定不存在的資料可以直接設定為安全資料,直接進行安全操作,否則才會近一步的進行安全管控。

如果資料的存在性發生變化,布隆過濾器是否允許對新增過的元素刪除?

傳統的布隆過濾器是不允許刪除的!
原因如下:
1、無法確定元素是否存在,如果是可能存在的結果,此時會導致誤刪。
2、即使真的確定元素是存在的,也無法刪除。因為不確定對應的value是否也存在其他元素的對映。


應該如何設定hash函式的個數和布隆過濾器的長度呢?
很顯然,如果布隆過濾器的長度設定的過小的話,很快所有的位置都會為1, 此時過濾的結果都是可能存在,
模糊結果的概率就會加大。如果設定的過大的話,則大部分空間都是0,此時又浪費了空間。
就像hashmap一樣,一方面要做到不浪費空間,另外一方面要做到儘可能的降低碰撞。
所以我們需要根據hash 的個數,過濾器的長度,可能存在的元素的數量,對模糊結果的概率(誤判率)得出一個估算。
總體的形式如下:
上圖是誤判率的計算公式。
下圖是對應的概率曲線。

k為hash公式個數,m為桶數,p為誤判率的,n代表資料量

這裡還有一些其他方面的問題:

1、布隆過濾器是不是更浪費空間?

並沒有,傳統過濾器的桶是使用bit來存值的,每個槽位只佔用一個1個bit位

2、多個hash之前的計算有重疊怎麼辦,比如hash1和hash2的運算結果相同,這樣就會使碰撞的概率變大?

這裡可以採用每個hash值對應一個單獨的小桶(或大桶的一部分)來存放,去除掉結果重複的影響。

 

相關文章