zoukankan      html  css  js  c++  java
  • 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 的空间

  • 相关阅读:
    PostgreSQL数据库笔记
    LayUI
    Spring
    Mybatis
    Mybatis生成
    server服务器信息页面添加步骤
    Java数据类型和MySql数据类型对应表
    空字符串
    json解析尖括号<>
    JSON--List集合转换成JSON对象
  • 原文地址:https://www.cnblogs.com/HKUI/p/10520628.html
Copyright © 2011-2022 走看看