Redis HyperLogLog 是用來做基數統計的算法,HyperLogLog 的優點是,在輸入元素的數量或者體積非常非常大時,計算基數所需的空間總是固定 的、並且是很小的。
在 Redis 里面,每個 HyperLogLog 鍵只需要花費 12 KB 內存,就可以計算接近 2^64 個不同元素的基 數。這和計算基數時,元素越多耗費內存就越多的集合形成鮮明對比。
因為 HyperLogLog 只會根據輸入元素來計算基數,而不會儲存輸入元素本身,所以 HyperLogLog 不能像集合那樣,返回輸入的各個元素。
- HyperLogLog是一種算法,並非redis獨有
- 目的是做基數統計,故不是集合,不會保存元數據,只記錄數量而不是數值。 耗空間極小,支持輸入非常體積的數據量
- 核心是基數估算算法,主要表現為計算時內存的使用和數據合並的處理。最終數值存在一定誤差
- redis中每個hyperloglog key占用了12K的內存用於標記基數(官方文檔)
- pfadd命令並不會一次性分配12k內存,而是隨着基數的增加而逐漸增加內存分配;而pfmerge操作則會將sourcekey合並后存儲在12k大小的key中,這由hyperloglog合並操作的原理(兩個
- hyperloglog合並時需要單獨比較每個桶的值)可以很容易理解。
- 誤差說明:基數估計的結果是一個帶有 0.81% 標准錯誤(standard error)的近似值。是可接受的范圍
- Redis 對 HyperLogLog 的存儲進行了優化,在計數比較小時,它的存儲空間采用稀疏矩陣存儲,空間占用很小,僅僅在計數慢慢變大,稀疏矩陣占用空間漸漸超過了閾值時才會一次性轉變成稠密矩陣,才會占用 12k 的空間
pfadd 添加
- 影響基數估值則返回1否則返回0.若key不存在則創建
- 時間復雜度O(1)
127.0.0.1:6379> pfadd m1 1 2 3 4 1 2 3 2 2 2 2
(integer) 1
pfcount 獲得基數值
- 得到基數值,叫做去重值(1,1,2,2,3)的插入pfcount得到的是3
- 可一次統計多個key
- 時間復雜度為O(N),N為key的個數
- 返回值是一個帶有 0.81% 標准錯誤(standard error)的近似值.
127.0.0.1:6379> pfadd m1 1 2 3 4 1 2 3 2 2 2 2 (integer) 1 127.0.0.1:6379> pfcount m1 (integer) 4
pfmerge 合並多個key
- 取多個key的並集
- 命令只會返回 OK.
- 時間復雜度為O(N)
127.0.0.1:6379> pfadd m1 1 2 3 4 1 2 3 2 2 2 2 (integer) 1 127.0.0.1:6379> pfcount m1 (integer) 4 127.0.0.1:6379> pfadd m2 3 3 3 4 4 4 5 5 5 6 6 6 1 (integer) 1 127.0.0.1:6379> pfcount m2 (integer) 5 127.0.0.1:6379> pfmerge mergeDes m1 m2 OK 127.0.0.1:6379> pfcount mergeDes (integer) 6
應用場景
說明:
基數不大,數據量不大就用不上,會有點大材小用浪費空間
有局限性,就是只能統計基數數量,而沒辦法去知道具體的內容是什么
和bitmap相比,屬於兩種特定統計情況,簡單來說,HyperLogLog 去重比 bitmap 方便很多
一般可以bitmap和hyperloglog配合使用,bitmap標識哪些用戶活躍,hyperloglog計數
一般使用:
統計注冊 IP 數
統計每日訪問 IP 數
統計頁面實時 UV 數
統計在線用戶數
統計用戶每天搜索不同詞條的個數