Bloom Filter 布隆過濾器

Wind__F發表於2020-12-25

hash function hash函式

通過計算得到一個資料的hash值的函式
md5、sha1……好像都是對一個資料反覆進行了大量的二進位制運算,比如:或、與……,具體實現看原始碼

Features:

  1. (在使用同一個hash function的前提下)相同的輸入有相同的輸出,不同輸入均勻分佈(但是不同的輸入也可能計算出的hash值是一樣的,因為輸入域是無限的 輸出域是固定數量(16位的16進位制)、固定資料的)
  2. hash function計算得出的hash值長度固定
  3. hash函式與輸入的順序無關,會均勻分佈,比如:有一個s域 0~99 經過hash函式計算後又 % array的size,就會在這個array陣列上均勻分佈
  4. 一個域均勻分佈,那麼它取模(%)後還是均勻分佈的

雜湊分佈是評判一個hash function優劣的標準,也就是說使用hash function計算出的陣列下標位置是會做到均勻分佈的,
但是雜湊分佈和陣列容量大小有關,隨著底層結構 陣列 的可使用容量的減少,會增大發生hash衝突的概率,所以需要使用負載因子來判斷何時需要resize陣列的容量

hash擴容 resize:

每次擴容都會是現在容量大小的2倍,那麼如果擴容到N的大小,那麼時間複雜度就是logN,但是擴容後還需要對原來的資料進行重新rehash,每次擴容的時間複雜度應該就是N了,那麼多次擴容的總時間複雜度就是N * logN

resize還可以後臺操作,不佔用主執行緒的時間

hash函式在大資料領域經常使用

布隆過濾器 Bloom Filter

作用:

解決一個數值是否存在某個範圍內,如果使用hashMap會造成很大的記憶體佔用。

比如:不安全網頁的黑名單包含100億個黑名單網頁,每個網頁的URL最多佔用64位元組。現在想要實現一種網頁過濾系統,可以根據網頁的URL判斷該網站是否在黑名單上,請設計該系統。要求該系統允許有萬分之一以下的判斷失誤率,並且使用的額外空間不要超過30G。

這個問題如果使用hashMap來儲存黑名單,有100億個URL,每個URL最多佔用64位元組,就是640G的記憶體空間,所以Bloom Filter就登場了。

Bloom Filter使用的是一個bitMap,即bit陣列,每一個bit都代表了一資料,所以資料的單位就從原來的byte位元組縮減到了bit

原理:

一個資料通過一系列的hash function,得到多個hash值,對這多個hash值進行計算,計算得到bitmap中的某個下標位置,然後將該下標的元素置為1。

如果在之後的計算中計算出的下標位置已經為1,再繼續置為1。

如果在之後查詢中,對一個資料使用k個hash function計算,計算得出的k個下標中有1個下標不是1,那麼這個資料不在Bloom Filter中,如果全為1,才在。因為如果一個資料在Bloom Filter中,它計算出的下標應該全為1才對。

計算邏輯:

使用計算出的hash值進行%取餘計算得到bitmap中的下標位置

(一般使用hash function對一個資料計算 計算得出陣列下標,然後在陣列中儲存資料 或者 標記為1,但是Bloom Filter不是這樣,

Bloom Filter使用了k個hash function,計算得出k個hash值,再對k個hash值進行計算得出陣列下標 標記為1,這整個過程就代表這個資料進到Bloom Filter裡來了。

所以bitmap就要很大,因為如果是100億個資料,每個資料都要使用k個hash function計算得出k個下標,如果bitmap容量比100億小,操作完後bitmap全1了 還查什麼,這失誤率不就100%了嘛。

所以也可以得出 可以通過調整hash function的個數 和 bitmap的容量 來得到失誤率。

bitmap容量多大合適呢?bitmap容量與 失誤率 和 hash function個數 有關)

公式:

Bloom Filter的大小m,失誤率p,樣本數量n,比如:樣本數量100億,失誤率萬分之一 即0.01%
在這裡插入圖片描述
根據公式計算出m=19.19n,向上取整為20n,即需要2000億個bit,也就是25GB。

hash function個數k
在這裡插入圖片描述
因為我們在確定布隆過濾器大小的過程中選擇了向上取整,所以還要用如下公式確定布隆過濾器真實的失誤率為
在這裡插入圖片描述
根據這個公式算出真實的失誤率為0.006%,這是比0.01%更低的失誤率,雜湊函式本身不佔用什麼空間,所以使用的空間就是bitMap的大小(即25GB),伺服器的記憶體都可以達到這個級別,所有要求達標。

優點:

節省空間佔用、查詢效率也快

缺點:

有一定失誤率、刪除困難

失誤率:因為hash function有不同的輸入也會有相同輸出的問題,所以會出現某個在黑名單中不存在的資料但是經過hash function計算後再計算出下標位置後發現該位置為1的情況

刪除困難:某個資料不在名單中了,將bitmap中的下標位置置為0了,但是由於其他資料在這個下標位置置為1過,現在是0了,就會造成之後查詢時,原本在黑名單中的這個下標的資料訪問時,由於已經是0了,就代表不在黑名單中,所以這個資料就可以和正常資料一樣任意訪問了,產生資料不安全的問題

(與hashMap不同的是hashMap使用hash function計算出hash值後再計算出下標位置後會儲存資料,所以發生hash碰撞後因為資料的不同不會失誤的覆蓋掉不同的資料,而Bloom Filter使用hash function計算出hash值後再計算出下標位置後會置為1,所以之後查詢時,不同的資料使用hash function計算出hash值後再計算出下標位置後無法判斷是否是相同的資料置為1的,所以就會發生誤判,存在失誤率)

使用場景:

  1. 在大資料量的場景下 比如:上億資料,計算某個資料是否存在
  2. 快取穿透

問:

為什麼使用多個hash function?是為了使用多個結果來證明某個資料存在嗎?還是其他別的原因?

一個資料使用多個hash function後,計算出來的hash值不一樣嗎?
多個hash函式的邏輯是不同的,比如:雖然是相同的輸入必會有相同的輸出,但也只是在使用同一種hash function的前提下,如果對同一個資料分別使用md5、sha1計算出的hash值就是不一樣的。

tips: Bloom Filter因為使用hash function,而且不像hashMap一樣儲存了資料,只是將制定位置置為了1,所以會因為hash衝突有失誤率,在建模時,就需要根據想要達到的失誤率來定義bitmap的大小、hash function的個數。

可供使用的第三方:

guava
redis(需要自己建立bitmap、定義bitmap的大小、hash function的個數、hash function的邏輯實現、手動標記bitmap中的下標位置)

hint:

單點登入CAS時,每個伺服器請求統一認證伺服器後,會在本地伺服器上快取cookie,因為如果每次請求都去請求統一認證伺服器 對伺服器有壓力,這就和平時使用瀏覽器訪問某個網站時一樣,第一次請求伺服器並快取,第二次後就從快取中獲取

相關文章