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


pfadd

用法和sadd一樣

pfcount

用法和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

當數據大時看看不精確率

<?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個時出現誤差

下面看誤差幾率

<?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也可以接受

誤差率也不算高。然后我們把上面的腳本再跑一邊,也就相當於將數據重復加入一邊,查看輸出,可以發現,pfcount 的結果沒有任何改變,還是 997593,說明它確實具備去重功能

pfmerge

  • 用於將多個 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 所使用的空間那真是可以使用千斤對比四兩來形容了

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


免責聲明!

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



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