Redis-HyperLogLog

HyperLogLog命令是redis在2.8版本中加入的,Redis中HyperLogLog是用来做基数统计的。

HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的、并且是很小的,因此每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 264 个不同元素的基数。但是HyperLogLog也存在缺点,就是它是估计基数的算法,所以会有一定误差0.81%,而且无法获取具体的元素值。因此应用在对准确性不是很重要的场景,例如:QQ同时在线人数,网站IP访问数量等等。

详情可以参考:https://chenjiehua.me/database/hyperloglog-bigdata.html
https://blog.csdn.net/firenet1/article/details/77247649

顺便附上本地测试的小例子:

package com.redis.hyperLoglog;

import com.redis.util.RedisUtil;
import org.junit.jupiter.api.Test;
import redis.clients.jedis.Jedis;

/**
 * HyperLoglog
 * 基数计数(cardinality counting)通常用来统计一个集合中不重复的元素个数,例如统计某个网站的UV,
 * 或者用户搜索网站的关键词数量。数据分析、网络监控及数据库优化等领域都会涉及到基数计数的需求。
 * 要实现基数计数,最简单的做法是记录集合中所有不重复的元素集合Su,当新来一个元素xi,若S​u中不包含元素x​i,则将x​i
 ​​* 加入S​u,否则不加入,计数值就是S​u的元素数量。这种做法存在两个问题:
 * 1.当统计的数据量变大时,相应的存储内存也会线性增长;
 * 2.当集合S​u变大,判断其是否包含新加入元素x​i的成本变大
 * 大数据量背景下,要实现基数计数,首先需要确定存储统计数据的方案,以及如何根据存储的数据计算基数值;
 * 另外还有一些场景下需要融合多个独立统计的基数值,例如对一个网站分别统计了三天的UV,
 * 现在需要知道这三天的UV总量是多少,怎么融合多个统计值。
 *
 */
public class HyperLoglogTest {

    /**
     * 数据结构为HyperLoglog的数据存储
     */
    @Test
    public void pfadd(){
        Jedis jedis = RedisUtil.getJedis();
        Long log1 = jedis.pfadd("log1", "1", "2", "3", "4");
        System.out.println("返回值:"+log1);
        Long log2 = jedis.pfadd("log2",  "5", "6", "7", "7", "7");
        System.out.println("返回值:"+log2);
        Long log3 = jedis.pfadd("log3",   "7","8");
        System.out.println("返回值:"+log3);
    }

    /**
     * 数据结构为HyperLoglog的数据长度(基数)
     */
    @Test
    public void pfcount(){
        Jedis jedis = RedisUtil.getJedis();
        long log1 = jedis.pfcount("log1");
        System.out.println("返回值:"+log1);
        long log2 = jedis.pfcount("log2");
        System.out.println("返回值:"+log2);
        long log3 = jedis.pfcount("log3");
        System.out.println("返回值:"+log3);
    }


    /**
     * 将多个HyperLoglog合并,合并到log1中,log2和log3为原始值。
     * 从后台查看log1会发现log1占用的空间会明显的增大
     */
    @Test
    public void pfmerge(){
        Jedis jedis = RedisUtil.getJedis();
        String pfmerge = jedis.pfmerge("log1", "log2","log3");
        System.out.println("返回值:pfmerge:"+pfmerge);

        System.out.println("================================");

        long log1 = jedis.pfcount("log1");
        System.out.println("返回值:"+log1);
        long log2 = jedis.pfcount("log2");
        System.out.println("返回值:"+log2);
        long log3 = jedis.pfcount("log3");
        System.out.println("返回值:"+log3);
    }

}

猜你喜欢

转载自blog.csdn.net/jinjin603/article/details/80769686