HyperLogLog(不精確的去重計數方案)

pfaddphp

用法和sadd同樣
java

pfcountpython


用法和scard同樣

127.0.0.1:6379> get lan
(nil)
127.0.0.1:6379> pfadd lan js
(integer) 1
127.0.0.1:6379> pfadd lan php
(integer) 1
127.0.0.1:6379> pfcount lan
(integer) 2
127.0.0.1:6379> pfadd lan php
(integer) 0
127.0.0.1:6379> pfcount lan
(integer) 2
127.0.0.1:6379> pfadd lan java python lua
(integer) 1
127.0.0.1:6379> pfcount lan
(integer) 5

當數據大時看看不精確率redis

<?php
$num=$argv[1]??200;
echo $num.PHP_EOL;

$redis=new redis();
$redis->connect('127.0.0.1',6379);
$redis->del('users');
for($i=1;$i<=$num;$i++){
    $r=$redis->pfadd('users',['user_'.$i]);
    $total=$redis->pfcount('users');
    if($total!=$i){
        echo $r.'-----i='.$i."----pfcount=".$total.PHP_EOL;
        break;
    }
}
[root@centos1 php]# php redis_hyperloglog.php 500
500
1-----i=128----pfcount=129

第128個時出現偏差centos

下面看偏差概率優化

<?php
$num=$argv[1]??200;
echo $num.PHP_EOL;

$redis=new redis();
$redis->connect('127.0.0.1',6379);
$redis->del('users');
for($i=1;$i<=$num;$i++){
    $r=$redis->pfadd('users',['user_'.$i]);
    $total=$redis->pfcount('users');
    if($i == $num){
        echo 'i='.$i."----pfcount=".$total.'---->'.($total-$i).'----'.($total-$i)/$i.PHP_EOL;
    }
}
[root@centos1 php]# php redis_hyperloglog.php 500
500
i=500----pfcount=500---->0----0
[root@centos1 php]# php redis_hyperloglog.php 1000
1000
i=1000----pfcount=999---->-1-----0.001

[root@centos1 php]# php redis_hyperloglog.php 5000
5000
i=5000----pfcount=4996---->-4-----0.0008
[root@centos1 php]# php redis_hyperloglog.php 50000
50000
i=50000----pfcount=50115---->115----0.0023


[root@centos1 php]# php redis_hyperloglog.php 10000
10000
i=10000----pfcount=10009---->9----0.0009
[root@centos1 php]# php redis_hyperloglog.php 100000
100000
i=100000----pfcount=99839---->-161-----0.00161
[root@centos1 php]# php redis_hyperloglog.php 1000000
1000000
i=1000000----pfcount=997593---->-2407-----0.002407

100w偏差率在0.002407也能夠接受lua

偏差率也不算高。而後咱們把上面的腳本再跑一邊,也就至關於將數據重複加入一邊,查看輸出,能夠發現,pfcount 的結果沒有任何改變,仍是 997593,說明它確實具有去重功能code

pfmergeget

  • 用於將多個 pf 計數值累加在一塊兒造成一個新的 pf 值
127.0.0.1:6379> pfadd boy Tom John
(integer) 1
127.0.0.1:6379> pfadd girl Lily lucy Andy
(integer) 1
127.0.0.1:6379> pfmerge student boy girl
OK
127.0.0.1:6379> pfcount student
(integer) 5

HyperLogLog 它須要佔據必定 12k 的存儲空間,因此它不適合統計單個用戶相關的數據。若是你的用戶上億,能夠算算,這個空間成本是很是驚人的。可是相比 set 存儲方案,HyperLogLog 所使用的空間那真是可使用千斤對比四兩來形容了perl

Redis 對 HyperLogLog 的存儲進行了優化,在計數比較小時,它的存儲空間採用稀疏矩陣存儲,空間佔用很小,僅僅在計數慢慢變大,稀疏矩陣佔用空間漸漸超過了閾值時纔會一次性轉變成稠密矩陣,纔會佔用 12k 的空間

相關文章
相關標籤/搜索