Redis 中的布隆過濾器

2021-09-11 11:34:46 字數 1801 閱讀 2065

布隆過濾器是乙個神奇的資料結構,可以用來判斷乙個元素是否在乙個集合中。很常用的乙個功能是用來去重。在爬蟲中常見的乙個需求:目標** url 千千萬,怎麼判斷某個 url 爬蟲是否寵幸過?簡單點可以爬蟲每採集過乙個 url,就把這個 url 存入資料庫中,每次乙個新的 url 過來就到資料庫查詢下是否訪問過。

select

idfrom

table

where

url = ''

複製**

但是隨著爬蟲爬過的 url 越來越多,每次請求前都要訪問資料庫一次,並且對於這種字串的 sql 查詢效率並不高。除了資料庫之外,使用 redis 的 set 結構也可以滿足這個需求,並且效能優於資料庫。但是 redis 也存在乙個問題:耗費過多的記憶體。這個時候布隆過濾器就很橫的出場了:這個問題讓我來。

相比於資料庫和 redis,使用布隆過濾器可以很好的避免效能和記憶體占用的問題。

布隆過濾器本質是乙個位陣列,位陣列就是陣列的每個元素都只占用 1 bit 。每個元素只能是 0 或者 1。這樣申請乙個 10000 個元素的位陣列只占用 10000 / 8 = 1250 b 的空間。布隆過濾器除了乙個位陣列,還有 k 個雜湊函式。當乙個元素加入布隆過濾器中的時候,會進行如下操作:

舉個?,假設布隆過濾器有 3 個雜湊函式:f1, f2, f3 和乙個位陣列arr。現在要把插入布隆過濾器中:

當要判斷乙個值是否在布隆過濾器中,對元素再次進行雜湊計算,得到值之後判斷位陣列中的每個元素是否都為 1,如果值都為 1,那麼說明這個值在布隆過濾器中,如果存在乙個值不為 1,說明該元素不在布隆過濾器中。

看不懂文字看下面的靈魂畫手的**釋???

看了上面的說明,必然會提出乙個問題:當插入的元素原來越多,位陣列中被置為 1 的位置就越多,當乙個不在布隆過濾器中的元素,經過雜湊計算之後,得到的值在位陣列中查詢,有可能這些位置也都被置為 1。這樣乙個不存在布隆過濾器中的也有可能被誤判成在布隆過濾器中。但是如果布隆過濾器判斷說乙個元素不在布隆過濾器中,那麼這個值就一定不在布隆過濾器中。簡單來說:

這個布隆過濾器的缺陷放到上面爬蟲的需求中,可能存在某些沒有訪問過的 url 可能會被誤判為訪問過,但是如果是訪問過的 url 一定不會被誤判為沒訪問過。

redis 在 4.0 的版本中加入了 module 功能,布隆過濾器可以通過 module 的形式新增到 redis 中,所以使用 redis 4.0 以上的版本可以通重載入 module 來使用 redis 中的布隆過濾器。但是這不是最簡單的方式,使用 docker 可以直接在 redis 中體驗布隆過濾器。

> docker run -d -p 6379:6379 --name bloomfilter redislabs/rebloom

> docker exec -it bloomfilter redis-cli

複製**

redis 布隆過濾器主要就兩個命令:

上面說過布隆過濾器存在誤判的情況,在 redis 中有兩個值決定布隆過濾器的準確率:

redis 中有乙個命令可以來設定這兩個值:

bf.reserve urls 0.01 100

複製**

三個引數的含義:

使用這個命令要注意一點:執行這個命令之前過濾器的名字應該不存在,如果執行之前就存在會報錯:(error) err item exists

Redis 布隆過濾器

實現原理 對的資料肯定是對的,錯的資料不能保證是對的。解釋如下 之前新增到容器中的資料,再次進行判斷是不是在這裡面,因為來過,槽位肯定我為1,所以判斷是不會出現問題的。容器中不存在,判斷是不是在容器中,可能其他的資料通過hash函式執行後把槽位占用了,所以存在一定的誤差。不能保證一定沒問題。hash...

Redis 布隆過濾器

想知道某乙個值是不是已經在 hyperloglog 結構裡面了,它就無能為力了,它只提供了 pfadd 和 pfcount 方法,沒有提供 pfcontains 這種方法。講個使用場景,比如我們在使用新聞客戶端看新聞時,它會給我們不停地推薦新的內容,它每次推薦時要去重,去掉那些已經看過的內容。問題來...

redis 布隆過濾器

為了應對redis快取穿透有三個大致方案 做好引數校驗,快取無效key,以及布隆過濾器。通過布隆過濾器我們可以非常方便地判斷乙個給定資料是否存在於海量資料中。我們需要的就是判斷 key 是否合法 具體是這樣做的 把所有可能存在的請求的值都存放在布隆過濾器中,當使用者請求過來,先判斷使用者發來的請求的...