淺談redis的HyperLogLog與布隆過濾器


首先,HyperLogLog與布隆過濾器都是針對大數據統計存儲應用場景下的知名算法。

HyperLogLog是在大數據的情況下關於數據基數的空間復雜度優化實現,布隆過濾器是在大數據情況下關於檢索一個元素是否在一個集合中的空間復雜度優化后的實現。

 

在傳統的數據量比較低的應用服務中,我們要實現數據基數和數據是否存在分析的功能,通常是簡單的把所有數據存儲下來,直接count一下就是基數了,而直接檢索一個元素是否在一個集合中也很簡單。

但隨着數據量的急劇增大,傳統的方式已經很難達到工程上的需求。過大的數據量無論是在存儲還是在查詢方面都存在巨大的挑戰,無論我們是用位存儲還是樹結構存儲等方式來優化,都沒法達到大數據時代的要求或者是性價比太低。

於是HyperLogLog與布隆過濾器這兩個算法就很好的派上了用場。他們的使用可以極大的節約存儲空間,作為代價,則是犧牲了一個小概率的准確性,這可以很好的達到工程上的需求,對於那些要求准確度沒那么高,但數據量巨大的需求是非常合適的。

 

HyperLogLog原理

最直白的解釋是,給定一個集合 S,對集合中的每一個元素,我們做一個哈希,假設生成一個 16 位的比特串,從所有生成的比特串中挑選出前面連續 0 次數最多的比特串,假設為 0000000011010110,連續 0 的次數為 8,因此我們可以估計該集合 S 的基數為 2^9。當然單獨用這樣的單一估計偶然性較大,導致誤差較大,因此在實際的 HyperLogLog 算法中,采取分桶平均原理了來消除誤差。(這段話引用了 HyperLogLog 原理  中的描述,還有一些細節實現 感興趣可閱讀 https://blockchain.iethpay.com/hyperloglog-theory.html

特點:實現犧牲了一定的准確度(在一些場景下是可以忽略的),但卻實現了空間復雜度上的極大的壓縮,可以說是性價比很高的。

雖然基數不完全准確,但是可以符合,隨着數量的遞增,基數也是遞增的。

 

布隆過濾器原理

 

布隆過濾器(Bloom Filter)的核心實現是一個超大的位數組和幾個哈希函數。假設位數組的長度為m,哈希函數的個數為k,以上圖為例,具體的操作流程:假設集合里面有3個元素{x, y, z},哈希函數的個數為3。首先將位數組進行初始化,將里面每個位都設置為0。對於集合里面的每一個元素,將元素依次通過3個哈希函數進行映射,每次映射都會產生一個哈希值,這個值對應位數組上面的一個點,然后將位數組對應的位置標記為1。查詢W元素是否存在集合中的時候,同樣的方法將W通過哈希映射到位數組上的3個點。如果3個點的其中有一個點不為1,則可以判斷該元素一定不存在集合中。反之,如果3個點都為1,則該元素可能存在集合中。注意:此處不能判斷該元素是否一定存在集合中,可能存在一定的誤判率。可以從圖中可以看到:假設某個元素通過映射對應下標為4,5,6這3個點。雖然這3個點都為1,但是很明顯這3個點是不同元素經過哈希得到的位置,因此這種情況說明元素雖然不在集合中,也可能對應的都是1,這是誤判率存在的原因。(這段話與圖片引用於 布隆過濾器(Bloom Filter)的原理和實現  中的描述,還有一些細節實現 感興趣可閱讀 https://www.cnblogs.com/cpselvis/p/6265825.html

特點:巧妙的使用hash算法和bitmap位存儲的方式,極大的節約了空間。

       由於主要用的是hash算法的特點,所有滿足和hash算法相同的規則:當過濾器返回 true時(表示很有可能該值是存在的),有一定概率是誤判的,即可能不存在;當過濾器返回false時(表示確定不存在),是可以完全相信的。

       我們換個數據的角度來看規則:當數據添加到布隆過濾器中時,對該數據的查詢一定會返回true;當數據沒有插入過濾器時,對該數據的查詢大部分情況返回false,但有小概率返回true,也就是誤判。

   我們知道它最終滿足的規則和hash的規則是一致的,只是組合了多個hash,使用了bitmap來存儲,大大優化了存儲的空間和判斷的效率。

 

redis中的HyperLogLog

在redis中對HyperLogLog 的支持早在2.8.9的時候就有了。它的操作非常簡單

  • PFADD  給HyperLogLog添加值
  • PFCOUNT 獲取基數
  • PFMERGE 合並兩個HyperLogLog數據(完美合並,分別添加和統一添加的結果是一致的)

 

redis中的布隆過濾器

 在redis中的布隆過濾器的支持是在redis4.0后支持插件的情況下,通過插件的方式實現的 ,redis的布隆過濾器插件地址:https://github.com/RedisLabsModules/rebloom

它的操作也很簡單,以下為幾個主要命令,其它命令請參考文檔 https://github.com/RedisLabsModules/rebloom/blob/master/docs/Bloom_Commands.md

 

BF.RESERVE {key} {error_rate} {size}   創建一個布隆過濾器   key為redis存儲鍵值,error_rate 為錯誤率(大於0,小於1),size為預計存儲的數量(size是比較關鍵的,需要根據自己的需求情況合理估計,設置太小的話會增大錯誤率,設置太大會占用過多不必要的空間)
BF.ADD {key} {item}  添加值到布隆過濾器中(當過濾器不存在的時候會,會以默認值自動創建一個,建議最好提前創建好)  key為redis存儲鍵值,item為值(如需要添加多個,請使用BF.MADD 可同時添加多個)
BF.EXISTS {key} {item}  判斷值是否存在過濾器中  true(表示很可能存在) false (表示絕對不存在)

參考文章:

https://blockchain.iethpay.com/hyperloglog-theory.html   hyperloglog原理

https://www.cnblogs.com/cpselvis/p/6265825.html   布隆過濾器原理

http://redisdoc.com/hyperloglog/index.html   redis的hyperloglog的使用

https://github.com/RedisLabsModules/rebloom/blob/master/docs/Bloom_Commands.md  redis的布隆過濾器的使用

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM