一、簡介
1 布隆過濾器的定義
布隆過濾器是一種空間效率高、誤判率可控的數(shù)據(jù)結構,通常用于檢索一個元素是否在一個集合中。它是由一個比特向量和多個哈希函數(shù)組成的。布隆過濾器可以用于快速檢測一個元素是否存在于一個集合中,其主要優(yōu)點是省內存缺點是有一定的誤識別率和刪除困難。
2 Redis 布隆過濾器的特點
- Redis 布隆過濾器采用了 Redis 自身的數(shù)據(jù)結構實現(xiàn),支持數(shù)據(jù)持久化,重啟后依然有效
- 在 Redis 中使用布隆過濾器需要先安裝 RedisBloom 模塊
- Redis 布隆過濾器使用多個哈希函數(shù),并使用不同的隨機種子在一定程度上降低了誤判率
- Redis 布隆過濾器可以設置錯誤率和元素數(shù)量通過調整這些參數(shù)可以控制誤判率
3 Redis 布隆過濾器的應用場景
- 郵箱黑名單、敏感詞過濾
- 在搜索引擎中過濾掉爬蟲或者惡意軟件等
- 在數(shù)據(jù)庫中避免重復插入相同數(shù)據(jù)
- 在網(wǎng)站訪問中,可以使用布隆過濾器緩存那些已經(jīng)訪問過的頁面
二、原理分析
1 布隆過濾器的基本原理
假設哈希函數(shù)個數(shù)為 k 每個比特位被設置多少次記為 m,n 為元素數(shù)量,則誤判率為 (1 - e(-kn/m))^k。當誤判率為 p 時選取最優(yōu)的哈希函數(shù)個數(shù) k 和比特位長度 m 可以使空間利用更加高效
代碼示例
public class BloomFilter {
private int size;
private int[] hashes;
private BitSet bits;
public BloomFilter(int size, int[] hashes) {
this.size = size;
this.hashes = hashes;
this.bits = new BitSet(size);
}
public void add(String value) {
for (int hash : hashes) {
int position = Math.abs(value.hashCode() * hash) % size;
bits.set(position, true);
}
}
public boolean contains(String value) {
for (int hash : hashes) {
int position = Math.abs(value.hashCode() * hash) % size;
if (!bits.get(position)) {
return false;
}
}
return true;
}
}
2 布隆過濾器的實現(xiàn)原理
- 創(chuàng)建 Redis 布隆過濾器時需要指定誤判率和預期元素數(shù)量,Redis 客戶端會根據(jù)這些參數(shù)計算出最優(yōu)的比特位長度 m 和哈希函數(shù)個數(shù) k。
- Redis 使用 MurmurHash2 和 MurmurHash64A 兩個哈希函數(shù)計算各自的哈希值,來保證布隆過濾器的誤判率和運行效率。
- 將插入元素在 k 個哈希函數(shù)中生成對應的 k 個哈希值,并將比特向量的這些位置置為 1。
- 查找元素是同樣地使用 k 個哈希函數(shù)計算出 k 個哈希值,在比特向量的對應位置查找是否都為 1。
代碼示例
Jedis jedis = new Jedis("localhost", 6379);
jedis.getClient().sendCommand(BloomFilterCommands.RESERVE, "mybloom", "0.001", "100000");
jedis.getClient().sendCommand(BloomFilterCommands.ADD, "mybloom", "hello");
Response<Boolean> response = jedis.getClient().getBooleanReply();
response.get();
jedis.getClient().sendCommand(BloomFilterCommands.EXISTS, "mybloom", "hello");
Response<Boolean> response = jedis.getClient().getBooleanReply();
response.get();
3 布隆過濾器的優(yōu)化策略
- 增加哈希函數(shù)的數(shù)量可以降低誤判率,但同時也會增加空間復雜度和計算時間
- 確定適當?shù)念A期元素數(shù)量和誤判率,避免過擬合和欠擬合
- 在 Redis 集群中,布隆過濾器可以通過將多個小的布隆過濾器組成一個大的布隆過濾器來協(xié)同工作,提高并發(fā)處理能力和存儲效率
三、Redis 布隆過濾器的實踐
1 布隆過濾器的安裝和配置
Redis 布隆過濾器需要在 Redis 中進行安裝和配置才能夠使用。首先需要在 Redis 安裝目錄下的 src
文件夾中找到 redis-trib.rb
文件。
# 進入 Redis 安裝目錄
cd xxx/redis-xx
# 執(zhí)行以下命令安裝 Redis 布隆過濾器
ruby src/redis-trib.rb create --replicas 1 ip:port ip:port ip:port ...
在上述命令中ip:port
需要替換為 Redis 節(jié)點的 IP 地址和端口號
2 布隆過濾器的使用方法
Redis 布隆過濾器常用于判斷某個元素是否在集合中可以通過以下命令進行使用:
# 向布隆過濾器添加元素
BF.ADD key element [element ...]
# 判斷元素是否在布隆過濾器中
BF.EXISTS key element
其中,key
表示 Redis 的鍵名,element
表示需要添加或判斷的元素。
3 布隆過濾器的性能測試和優(yōu)化
Redis 布隆過濾器可以通過以下命令來進行性能測試:
# 測試添加元素的速度
BF.RESERVE key 0.0001 10000
# 測試判斷元素是否在布隆過濾器中的速度
BF.EXISTS key element
需要注意的是在 BF.RESERVE
命令中,第一個參數(shù) key
代表 Redis 的鍵名,第二個參數(shù)為錯誤率即誤報的概率,第三個參數(shù)代表預期最大元素個數(shù)。
如果發(fā)現(xiàn) Redis 布隆過濾器性能較低,可以通過增加節(jié)點個數(shù)或降低錯誤率等方式進行優(yōu)化。
四、Redis 布隆過濾器的應用案例
1 布隆過濾器在網(wǎng)站防刷中的應用
Redis 布隆過濾器可以用于網(wǎng)站的防刷功能,通過判斷IP地址或者用戶行為是否已經(jīng)超出一定的次數(shù)來避免短時間內多次請求相同的資源。例如:
# 判斷 IP 地址是否已經(jīng)被封禁
if BF.EXISTS ip_bloom_filter ip {
return 403; # 返回禁止訪問的狀態(tài)碼
}
2 布隆過濾器在數(shù)據(jù)去重中的應用
在數(shù)據(jù)去重方面可以使用 Redis 布隆過濾器來避免在大規(guī)模數(shù)據(jù)處理中的重復計算,減少計算開銷,并且保證數(shù)據(jù)的唯一性
# 判斷文章是否已經(jīng)被處理過
if BF.EXISTS article_bloom_filter article_id {
continue; # 跳過本次循環(huán)
}
# 處理文章內容
process_article(article);
# 將文章 ID 添加到布隆過濾器中
BF.ADD article_bloom_filter article_id;
3 布隆過濾器在爬蟲去重中的應用
在爬蟲系統(tǒng)中為了避免重復爬取已經(jīng)存在的網(wǎng)頁,可以使用 Redis 布隆過濾器來記錄已經(jīng)訪問過的 URL文章來源:http://www.zghlxwxcb.cn/news/detail-485403.html
# 判斷 URL 是否已經(jīng)被訪問過
if BF.EXISTS url_bloom_filter url {
continue; # 跳過本次循環(huán)
}
# 訪問 URL
response = http.get(url);
# 將 URL 添加到布隆過濾器中
BF.ADD url_bloom_filter url;
通過以上的應用案例可以看出Redis 布隆過濾器具有在數(shù)據(jù)去重、防刷、爬蟲去重等方面的廣泛應用,并且可以有效地減少重復計算、避免誤報或者漏報等問題。文章來源地址http://www.zghlxwxcb.cn/news/detail-485403.html
五、Redis 布隆過濾器的優(yōu)缺點分析
1 布隆過濾器的優(yōu)點
- 布隆過濾器是一種空間效率高的數(shù)據(jù)結構可以代替?zhèn)鹘y(tǒng)的 List, Set 等數(shù)據(jù)結構,以達到節(jié)約內存的目的
- 布隆過濾器的插入和查詢時間復雜度都是 O(k),k 是哈希函數(shù)個數(shù),這個值可以根據(jù)數(shù)據(jù)量去調整,因此查詢效率非常高。
- 布隆過濾器可以用于判斷一個元素是否在集合中,可以用在緩存穿透的場景中。
2 布隆過濾器的缺點
- 布隆過濾器無法刪除元素,一旦添加了一個元素就無法刪除,因為刪除可能會影響其他元素的判斷結果
- 布隆過濾器的誤判率是存在的,這是由于多個元素映射到布隆過濾器的同一個位置,使得可能存在“誤判”情況
- 布隆過濾器的哈希函數(shù)個數(shù)和大小都需要事先確定,這在一些應用場景中可能不太容易確定。
3 布隆過濾器的適用場景
- 緩存穿透:如果緩存中不存在某個鍵對應的值,而且大量的請求又同時訪問該鍵,這時可以通過布隆過濾器過濾掉這些非法請求,降低了對后端系統(tǒng)的壓力。
- 網(wǎng)絡爬蟲:利用布隆過濾器判斷一個鏈接是否已經(jīng)被爬取過,避免重復抓取同一鏈接,提高爬蟲的效率。
- 黑名單過濾:將不良網(wǎng)址、IP 地址等加入到布隆過濾器中,當請求過來時直接使用布隆過濾器判斷是否需要過濾掉該請求。
到了這里,關于Redis 布隆過濾器的原理和實踐的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!