標籤:des ar 使用 strong sp 資料 on 2014 問題
如果我們要實現記錄網站每天訪問的獨立IP數量這樣的一個功能
集合實現:
使用集合來儲存每個訪客的 IP ,通過集合性質(集合中的每個元素都各不相同)來得到多個獨立 IP ,
然後通過調用 SCARD 命令來得出獨立 IP 的數量。
舉個例子,程式可以使用以下代碼來記錄 2014 年 8 月 15 日,每個網站訪客的 IP :
ip = get_vistor_ip()
SADD ‘2014.8.15::unique::ip‘ ip
然後使用以下代碼來獲得當天的唯一 IP 數量:
SCARD ‘2014.8.15::unique::ip‘
集合實現的問題
使用字串來儲存每個 IPv4 地址最多需要耗費 15 位元組(格式為 ‘XXX.XXX.XXX.XXX‘ ,比如
‘202.189.128.186‘)。
下表給出了使用集合記錄不同數量的獨立 IP 時,需要耗費的記憶體數量:
獨立 IP 數量一天一個月一年
一百萬15 MB 450 MB 5.4 GB
一千萬150 MB 4.5 GB 54 GB
一億1.5 GB 45 GB 540 GB
隨著集合記錄的 IP 越來越多,消耗的記憶體也會越來越多。
另外如果要儲存 IPv6 地址的話,需要的記憶體還會更多一些
為了更好地解決像獨立 IP 位址計算這種問題,
Redis 在 2.8.9 版本添加了 HyperLogLog 結構。
HyperLogLog介紹
HyperLogLog 可以接受多個元素作為輸入,並給出輸入元素的基數估算值:
• 基數:集合中不同元素的數量。比如 {‘apple‘, ‘banana‘, ‘cherry‘, ‘banana‘, ‘apple‘} 的基數就是 3 。
• 估算值:演算法給出的基數並不是精確的,可能會比實際稍微多一些或者稍微少一些,但會控制在合
理的範圍之內。
HyperLogLog 的優點是,即使輸入元素的數量或者體積非常非常大,計算基數所需的空間總是固定
的、並且是很小的。
在 Redis 裡面,每個 HyperLogLog 鍵只需要花費 12 KB 記憶體,就可以計算接近 2^64 個不同元素的基
數。這和計算基數時,元素越多耗費記憶體就越多的集合形成鮮明對比。
但是,因為 HyperLogLog 只會根據輸入元素來計算基數,而不會儲存輸入元素本身,所以
HyperLogLog 不能像集合那樣,返回輸入的各個元素。
將元素添加至 HyperLogLog
PFADD key element [element ...]
將任意數量的元素添加到指定的 HyperLogLog 裡面。
這個命令可能會對 HyperLogLog 進行修改,以便反映新的基數估算值,如果 HyperLogLog 的基數估算
值在命令執行之後出現了變化, 那麼命令返回 1 , 否則返回 0 。
命令的複雜度為 O(N) ,N 為被添加元素的數量。
返回給定 HyperLogLog 的基數估算值
PFCOUNT key [key ...]
當只給定一個 HyperLogLog 時,命令返回給定 HyperLogLog 的基數估算值。
當給定多個 HyperLogLog 時,命令會先對給定的 HyperLogLog 進行並集計算,得出一個合并後的
HyperLogLog ,然後返回這個合并 HyperLogLog 的基數估算值作為命令的結果(合并得出的
HyperLogLog 不會被儲存,使用之後就會被刪掉)。
當命令作用於單個 HyperLogLog 時, 複雜度為 O(1) , 並且具有非常低的平均常數時間。
當命令作用於多個 HyperLogLog 時, 複雜度為 O(N) ,並且常數時間也比處理單個 HyperLogLog 時要
大得多。
PFADD 和 PFCOUNT 的使用樣本
redis> PFADD unique::ip::counter ‘192.168.0.1‘
(integer) 1
redis> PFADD unique::ip::counter ‘127.0.0.1‘
(integer) 1
redis> PFADD unique::ip::counter ‘255.255.255.255‘
(integer) 1
redis> PFCOUNT unique::ip::counter
(integer) 3
合并多個 HyperLogLog
PFMERGE destkey sourcekey [sourcekey ...]
將多個 HyperLogLog 合并為一個 HyperLogLog ,合并後的 HyperLogLog 的基數估算值是通過對所有
給定 HyperLogLog 進行並集計算得出的。
命令的複雜度為 O(N) , 其中 N 為被合并的 HyperLogLog 數量, 不過這個命令的常數複雜度比較高。
PFMERGE 的使用樣本
redis> PFADD str1 "apple" "banana" "cherry"
(integer) 1
redis> PFCOUNT str1
(integer) 3
redis> PFADD str2 "apple" "cherry" "durian" "mongo"
(integer) 1
redis> PFCOUNT str2
(integer) 4
redis> PFMERGE str1&2 str1 str2
OK
redis> PFCOUNT str1&2
(integer) 5
HyperLogLog 實現獨立 IP 計算功能
獨立 IP 數量一天一個月一年一年(使用集合)
一百萬12 KB 360 KB 4.32 MB 5.4 GB
一千萬12 KB 360 KB 4.32 MB 54 GB
一億12 KB 360 KB 4.32 MB 540 GB
下表列出了使用 HyperLogLog 記錄不同數量的獨立 IP 時,需要耗費的記憶體數量:
可以看到,要統計相同數量的獨立 IP ,HyperLogLog 所需的記憶體要比集合少得多。
redis資料結構HyperLogLog