目錄昨天突然看到了乙個布隆過濾器的介紹和一些用法,感覺很新奇,也很有意思,剛好趁著週末來寫一篇部落格。
布隆過濾器?難道是這個?e起來,然後阻擋地方的飛行道具並減少傷害?
no!no!no!當然不是這個,一篇技術部落格怎麼會扯到遊戲呢?來來來,讓我們先看一下布隆的e技能。
堅不可摧
e布隆朝乙個方向舉起盾牌,持續3/3.25/3.5/3.75/4秒,並使來自目標方向的第一次攻擊變得無效。布隆還將攔截敵方的飛行道具,並將它們摧毀,減少30/32.5/35/37.5/40%的後續傷害。在舉盾期間,布隆獲得10%移動速度加成。
首先,我們設想乙個場景,在某次開發中,你被要求你的**的使用者名稱不能重複,你應該怎麼做?第一感覺當然就是將使用者名稱存到資料庫中間,然後當使用者註冊的時候,檢視資料庫是否存在這個使用者名稱即可。可是,當你的**使用者量很大的時候比如說一億,查詢資料庫毋庸置疑是乙個耗時的操作,這個時候,你突然想到了雜湊表,因為你知道雜湊表的查詢時間複雜度是o(1),可是我們可以算一下,乙個使用者名為四個漢字,乙個漢字占用兩個位元組(unicode情況下),那麼一共有八億個位元組。一共占用763m的記憶體(這個裡面不包括物件占用的空間,也不包括雜湊表中浪費的空間),而實際情況占用的空間會比這個多得多。
那麼有什麼好方法解決這個問題呢?這個就是我們要講的布隆過濾器。首先我們以布隆的技能來形象的解釋下布隆過濾器的優缺點:
布隆過濾器的原理和雜湊表的原理有點類似,同樣需要使用hash函式,但是在布隆過濾器中,需要使用多個hash函式。布隆過濾器的原理還是比較簡單的。
我們有乙個位陣列bitarray,對,就是乙個位陣列,長度位m。只存0和1那種。此時我們有乙個key,和k個hash函式,因此我們可以得到k個key被hash過後的數。然後我們分別對hash過後的值取餘(對m取餘)得到x,然後將bitarray中x位置置為1。
原理如下所示(**)
在前面我們介紹過布隆過濾器如果判斷資料存在,實際上資料也可能不存在。如果將布隆過濾器應用於垃圾郵件過濾系統,則就會出現「寧可錯殺一千,也決不放過乙個」的這種情況。那麼為什麼會造成這種情況呢?實際上,這就和雜湊表中雜湊衝突的情況一樣,因為可能會出現兩個key值經過k個hash函式之後,取餘之後的結果是一樣的。所以,在布隆過濾器中可能會出現誤判,所以有乙個概念叫做誤算率。
上面我們知道布隆過濾器中,有乙個誤算率,當然我們是想將誤判降低到最小(key的數量和陣列bitarray的長度都是確定的)。so,讓我們用數學公式來推導一下。
首先我們有n
個key,bitarray的長度位m
,hash函式的個數是k
,失誤率是p
(一般很小),推導如下:
誤判的概率:
如果hash函式足夠優秀(每乙個key都等概率的分配到陣列中的某乙個位置)。對於乙個hash函式來說,bitarray中某個位置被置1的概率是\(\frac\),則不被置1的概率是\(1-\frac\),因為我們有k個hash函式,所以在k個hash函式中,某個位置不被置1的概率是:
\[(1-\frac)^k
\]因為插入了n個key,某個位置置1的概率是:(不被置1的概率是\((1-\frac)^\))
\[1-(1-\frac)^
\]如果我們此時去查詢某個key是否存在,出現誤判(也就是說在bitarray中k個位置都出現了1)的概率是:
\[[1-(1-\frac)^]^
\]選擇最小的誤判概率:
根據數學知識我們知道:
\[ lim_(1+\frac)^ = e \\
等價於:\\
lim_(1+a)^} = e \\
\] 所以:
\[[1-(1-\frac)^]^ = [1-(1-\frac)^}]^ = [1-e^}]^k
\] 然後令\(a=e^}\) ,因此概率是:
\[f(k)=(1-a^)^k
\]我們需要求得便是\(f(k)\)的最小值。對\(f(k)\)進行變換求導:
\[\begin&f(k) = (1-a^k)^k \\&lnf(k) = kln(1-a^k) \\&然後進行求導\\ &\fracf'(k) = ln(1-a^k) - \frac\\&\because a=e^} \\&\therefore a < 1\\&\therefore 0< f(k)=(1-a^)^k <1\\&令f'(k) = 0,則 ln(1-a^k) - \frac =0\\&\therefore (1-a^k)ln(1-a^k) = ka^klna = a^kln\\&\therefore (1-a^k) = a^k \\&\therefore a^k = \frac\\&\therefore e^} = \frac \\&\therefore \frac = ln2 \\&\therefore k = \frac = 0.7\frac\\&所以誤判率p是:\\&[1-e^}]^k = (1-e^})^} \\&=(\frac)^}\\&≈0.6185^\frac&\end
\]從上面我們可以知道,如果想讓誤判率一直維持穩定,那麼則m和n要維持線性增加。當然,如果是其他變數保持不變,也可以用上面的方法進行求出。
在這裡我們可以很簡單的看出來,使用布隆過濾器之後,空間佔用率還是蠻低的,還是以上面的例子舉例:有一億個使用者,在我們保證保證錯誤率位0.01%的情況下,我們需要大概19億位的空間來儲存資料(大約是230m的空間)。其中需要的雜湊函式的個數\(k=13\)。相比前面還是節省了蠻多的空間。
markdown 寫數學公式還是蠻爽的(●'◡'●)
布隆過濾器
布隆過濾器 bloom filter 是1970年由布隆提出的。它實際上是乙個很長的二進位制向量和一系列隨機對映函式。布隆過濾器可以用於檢索乙個元素是否在乙個集合中。它的優點是空間效率和查詢時間都遠遠超過一般的演算法,缺點是有一定的誤識別率和刪除困難。如果想要判斷乙個元素是不是在乙個集合裡,一般想到...
布隆過濾器
布隆過濾器的概念 如果想要判斷乙個元素是不是在乙個集合裡,一般想到的是將所有元素儲存起來,然後通過比較確定。鍊錶,樹等等資料結構都是這種思路.但是隨著集合中元素的增加,我們需要的儲存空間越來越大,檢索速度也越來越慢 o n o logn 不過世界上還有一種叫作雜湊表 又叫 雜湊表,hash tabl...
布隆過濾器
如果想判斷乙個元素是不是在乙個集合裡,一般想到的是將集合中所有元素儲存起來,然後通過比較確定。鍊錶 樹 雜湊表 又叫雜湊表,hash table 等等資料結構都是這種思路。但是隨著集合中元素的增加,我們需要的儲存空間越來越大。同時檢索速度也越來越慢。bloom filter 是一種空間效率很高的隨機...