Redis系列1:深刻理解高效能Redis的本質
Redis系列2:資料持久化提高可用性
Redis系列3:高可用之主從架構
Redis系列4:高可用之Sentinel(哨兵模式)
Redis系列5:深入分析Cluster 叢集模式
追求效能極致:Redis6.0的多執行緒模型
追求效能極致:使用者端快取帶來的革命
Redis系列8:Bitmap實現億萬級資料計算
Redis系列9:Geo 型別賦能億級地圖位置計算
Redis系列10:HyperLogLog實現海量資料基數統計
Redis系列11:記憶體淘汰策略
Redis系列12:Redis 的事務機制
Redis系列13:分散式鎖實現
Redis系列14:使用List實現訊息佇列
Redis系列15:使用Stream實現訊息佇列
布隆過濾器(Bloom Filter)是 Redis 4.0 版本提供的新功能,我們一般將它當做外掛載入到 Redis 伺服器中,給 Redis 提供強大的去重功能。
它是一種概率性資料結構,可用於判斷一個元素是否存在於一個集合中。相比較之 Set 集合的去重功能,布隆過濾器空間上能節省 90% +,不足之處是去重率大約在 99% 左右,那就是有 1% 左右的誤判率,這種誤差是由布隆過濾器的自身結構決定的。
布隆過濾器(Bloom Filter)是一個高空間利用率的概率性資料結構,由二進位制向量(即位陣列)和一系列隨機對映函數(即雜湊函數)兩部分組成。
通過使用exists()來判斷某個元素是否存在於自身結構中。當布隆過濾器判定某個值存在時,其實這個值只是有可能存在;當它說某個值不存在時,那這個值肯定不存在,這個誤判概率大約在 1% 左右。
原理拆解如下:
當使用布隆過濾器新增 key 時,會使用不同的 hash 函數對 key 儲存的元素值進行雜湊計算,從而會得到多個雜湊值。根據雜湊值計算出一個整數索引值,將該索引值與位陣列長度做取餘運算,最終得到一個位陣列位置,並將該位置的值變為 1。每個 hash 函數都會計算出一個不同的位置,然後把陣列中與之對應的位置變為 1。這邊可能出現元素碰撞的情況,比如位置3,a元素和b元素的hash計算位置一致,所以出現了碰撞。
如果我們要判定一個元素是否存在,需要如下步驟:
為啥說是可能存在呢,因為上面說過了,雜湊函數出的結果會出現碰撞,所以布隆過濾器會存在誤判。
如上圖c,他的位置被其他元素的位置完全覆蓋,即使c沒有儲存,對應位置上也被a和b的Hash函數設定為1,這時候就可能誤判為c是有儲存的。
有概率存在這樣的 key,它們內容不同,但多次 Hash 後的 Hash 值都相同。
一般不會刪除元素,我們上面說了,因為可能存在碰撞情況,所以也有可能存在誤刪除情況。
刪除意味著需要將對應的 n 個 bits 位置設定為 0,其中有可能是其他元素對應的位。
比如圖中的b刪除之後,位置3的值也被設定為0,這樣a也可能會被判定為不存在。
我們在遇到資料量大的時候,為了去重並避免大批次的重複計算,可以考慮使用 Bloom Filter 進行過濾。
具體常用的經典場景如下:
如果是自己編譯安裝,可以從 github 下載,目前的latest 的 release 版本是 v2.4.5,下載地址如下:
https://github.com/RedisBloom/RedisBloom/releases/tag/v2.4.5
直接按照編譯的方式進行安裝:
# 解壓檔案:
tar -zxvf tar -zxvf RedisBloom-2.4.5.tar.gz
# 進入目錄:
cd RedisBloom-2.4.5
# 執行編譯命令,生成redisbloom.so 檔案:
make
# 拷貝至指定目錄:
cp redisbloom.so /usr/local/redis/RedisBloom-2.4.5/redisbloom.so
# 需要修改 redis.conf 檔案,新增 loadmodule設定,並重啟 Redis。
# 在redis組態檔里加入以下設定:
loadmodule /usr/local/redis/RedisBloom-2.4.5/redisbloom.so
# 設定完成後重啟redis服務:
redis-server /usr/local/redis/RedisBloom-2.4.5/redis.conf
# 測試是否安裝成功
127.0.0.1:6379> bf.add user brand
(integer) 1
127.0.0.1:6379> bf.exists user brand
(integer) 1
大致說了布隆過濾器的原理和使用場景,下一篇我們來看看實戰。