布隆過濾器是一種資料結構,比較巧妙的概率型資料結構,特點是高效地插入和查詢,可以用來告訴你某樣東西一定不存在或者可能存在。
相比於傳統的 list、set、map 等資料結構,它更高效、占用空間更少,但是缺點是其返回的結果是概率性的,而不是確切的。
我們考慮這樣乙個場景,你有乙個**並且擁有很多訪客,每當有使用者訪問時,你想知道這個ip是不是第一次訪問你的**。
為了完成這個功能,你很容易就會想到下面這個解決方案:
把訪客的ip存進乙個hash表中,每當有新的訪客到來時,先檢查雜湊表中是否有該訪客的ip,如果有則說明該訪客不是第一次訪問。
hash表的訪問時間複雜度都是o(1),效率很高,但是假設你的**已經被1億個使用者訪問過,每個ip的長度是15,那麼你一共需要15 * 100000000 = 1500000000bytes = 1.4g,這還沒考慮hash衝突的問題(hash表中的槽位越多,越浪費空間,槽位越少,效率越低)
如果把ip轉換成無符號的int型值來儲存,乙個ip需要占用4個位元組就行了,這時1億個ip占用的空間是4 * 100000000 = 400000000bytes = 380m,空間消耗降低了很多。
那還有沒有在不影響訪問效率的前提下更加節省空間的辦法呢?
32位無符號int型能表示的最大值是4294967295,所有的ip都在這個範圍內,我們可以用乙個bit位來表示某個ip是否出現過,如果出現過,就把代表該ip的bit位置為1,那麼我們最多需要429496729個bit就可以表示所有的ip了。舉個例子比如10.0.0.1轉換成int是167772161,那麼把長度為4294967295的bit陣列的第167772161個位置置為1即可,當有ip訪問時,只需要檢查該標誌位是否為1就行了。
4294967295bit = 536870912byte = 512m
bitset的侷限性
那針對這兩種情況有沒有解決辦法呢?
基於這種思想,bloomfilter誕生了。
bloom filter是一種空間效率很高的隨機資料結構,bloom filter 可以看做是對 bit-map 的擴充套件, 它的原理是:
當乙個元素被加入集合時,通過 k 個 hash 函式將這個元素對映成乙個位陣列(bit array)中的 k 個點,把它們置為 1。檢索時,我們只要看看這些點是不是都是 1 就(大約)知道集合中有沒有它了:
如果這些點有任何乙個 0,則被檢索元素一定不在;如果都是 1,則被檢索元素很可能在。
核心思想
布隆過濾器包括兩部分
redis 因其支援 setbit 和 getbit 操作,且純記憶體效能高等特點,因此天然就可以作為布隆過濾器來使用。
但是布隆過濾器的不當使用極易產生大value,增加 redis 阻塞風險,因此生成環境中建議對體積龐大的布隆過濾器進行拆分。
拆分的形式方法多種多樣,但是本質是不要將 hash(key) 之後的請求分散在多個節點的多個小 bitmap 上,
而是應該拆分成多個小 bitmap 之後,對乙個 key 的所有雜湊函式都落在這乙個小 bitmap 上。
使用hash演算法 + bitmap 實現
另外,既然你使用布隆過濾器來加速查詢和判斷是否存在,那麼效能很低的雜湊函式不是個好選擇,推薦murmurhash、fnv這些。
布隆過濾器
布隆過濾器 bloom filter 是1970年由布隆提出的。它實際上是乙個很長的二進位制向量和一系列隨機對映函式。布隆過濾器可以用於檢索乙個元素是否在乙個集合中。它的優點是空間效率和查詢時間都遠遠超過一般的演算法,缺點是有一定的誤識別率和刪除困難。如果想要判斷乙個元素是不是在乙個集合裡,一般想到...
布隆過濾器
布隆過濾器的概念 如果想要判斷乙個元素是不是在乙個集合裡,一般想到的是將所有元素儲存起來,然後通過比較確定。鍊錶,樹等等資料結構都是這種思路.但是隨著集合中元素的增加,我們需要的儲存空間越來越大,檢索速度也越來越慢 o n o logn 不過世界上還有一種叫作雜湊表 又叫 雜湊表,hash tabl...
布隆過濾器
如果想判斷乙個元素是不是在乙個集合裡,一般想到的是將集合中所有元素儲存起來,然後通過比較確定。鍊錶 樹 雜湊表 又叫雜湊表,hash table 等等資料結構都是這種思路。但是隨著集合中元素的增加,我們需要的儲存空間越來越大。同時檢索速度也越來越慢。bloom filter 是一種空間效率很高的隨機...