Redis--HyperLogLog的指令语法与使用场景举例(UV统计)

文章目录

      • 前言
      • HyperLogLog介绍
      • HyperLogLog指令使用
      • 使用场景:UV统计

前言

  • Redis除了常见的五种数据类型之外,其实还有一些少见的数据结构,如Geo,HyperLogLog等。虽然它们少见,但是作用却不容小觑。本文将介绍HyperLogLog指令的语法和使用场景。

HyperLogLog介绍

  • HyperLogLog是Redis提供的一种不准确(标准误差为0.81%)的去重计数方案。
  • 提到去重计数,第一个想到的数据结构就是集合set,set集合可以保存数据,并用scard准确地返回集合中的数据条数,但是若数据量很大,那么使用set集合就需要相当大的存储空间,这显然不是我们想看到的结果,而对于某些统计其实并不需要特别精确的结果。
  • 对于这种情况,HyperLogLog就可以发挥大用,HyperLogLog的优势在于无论存储的数据量有多大,它都只需要12KB的存储空间(可以计算接近2^64个不同的基数)。当然它只能统计数据集的个数,而不直接存放元素,不能试图用它保存元素。另外HyperLogLog对数据集的统计也不是完全准确的,存在一定误差,可能比实际情况多或少。

HyperLogLog指令使用

  • 增加计数: pfadd key element [element...]

  • 查询计数: pfcount key

  • 将多个HyperLogLog合并到一个HyperLogLog中: pfmerge destkey sourcekey [sourcekey ...]

使用场景:UV统计

  • HyperLogLog最适合的使用场景就是做UV的统计了,简直量身定制一般。一个爆款页面的UV可能有几千万,使用HyperLogLog可以节约存储空间,并且UV的统计允许存在一定的误差。

    补充:

    • pv(page view,浏览量)
      • 页面的浏览次数,衡量网站用户访问的网页数量;
      • 用户每打开一个页面就记录1次,多次打开同一页面则浏览量累计。
    • uv(unique visitor,独立访客)
    • 1天内访问某站点的人数(以cookie为依据);
    • 1天内同一访客的多次访问只计为1个访客。
    • ip(独立ip)
    • 指1天内使用不同ip地址的用户访问网站的数量;
    • 同一IP不管访问了几个页面,独立IP数均为1。
  • 代码实现: 在代码中提供了三个方法,分别对应pfadd添加页面的UV,pfcount获取页面的UV统计结果和pfmerge合并指定页面UV。

    java 复制代码
    public class UVByHyperLogLog {
        public static void main(String[] args) {
            Jedis jedis = new Jedis("127.0.0.1");
            jedis.del(UV_PAGE_1);
            jedis.del(UV_PAGE_2);
            jedis.del(UV_PAGE_1_2);
            
            for (int i = 0; i < 10000; i++) {
                String userid = "userid:"+Math.random()*100000;
                addCount(UV_PAGE_1,userid,jedis);
            }
            System.out.println("页面一的UV:"+getCount(UV_PAGE_1,jedis));
    
            jedis.del(UV_PAGE_2);
            for (int i = 0; i < 5000; i++) {
                String userid = "userid:"+Math.random()*100000;
                addCount(UV_PAGE_2,userid,jedis);
            }
            System.out.println("页面二的UV:"+getCount(UV_PAGE_2,jedis));
    
            //页面一和页面二合并后的UV 合并与的UV不等于两个UV的相加,一样是不精确的
            mergeCount(UV_PAGE_1_2, new String[]{UV_PAGE_1, UV_PAGE_2},jedis);
            System.out.println("合并后两个页面的UV总数"+getCount(UV_PAGE_1_2,jedis));
        }
    
        private static final String UV_PAGE_1 = "UV_PAGE_1";
        private static final String UV_PAGE_2 = "UV_PAGE_2";
    
        private static final String UV_PAGE_1_2 = "UV_PAGE_1_2";
        /**
         * 向HyperLogLog添加数据
         * @param key UV_KEY
         * @param userId 用户Id
         * @param jedis
         */
        public static void addCount(String key, String userId,Jedis jedis){
            jedis.pfadd(key,userId);
        }
    
        /**
         * 返回统计的结果
         * @param key
         * @param jedis
         * @return
         */
        public static long getCount(String key,Jedis jedis){
            return jedis.pfcount(key);
        }
    
        /**
         * 将多个pf计数合并为一个pf计数
         * @param newKey 合并后的新HyperLogLog的key
         * @param keys  要合并的HyperLogLog的key
         * @param jedis
         * @return
         */
        public static void mergeCount(String newKey,String[] keys,Jedis jedis){
            jedis.pfmerge(newKey,keys);
        }
    }
  • 测试结果:在上述main方法中,第一个for循环,模拟10000个用户访问页面一,第二个for循环模拟5000个用户访问页面二,通过HyperLogLog进行UV统计,输出统计结果,最后合并两个页面的统计值,观察结果后发现,HyperLogLog统计后的结果与实际结果存在误差,但是在数据量很大的情况下,这点误差误伤大雅。:

相关推荐
烛阴几秒前
Express入门必学三件套:路由、中间件、模板引擎全解析
javascript·后端·express
欧宸雅19 分钟前
Perl语言的文件系统
开发语言·后端·golang
uhakadotcom25 分钟前
使用 boto3 读取 AWS S3 文件的简单指南
后端·面试·github
程序猿chen44 分钟前
《JVM考古现场(十六):太初奇点——从普朗克常量到宇宙弦的编译风暴》
jvm·git·后端·程序人生·金融·java-ee·量子计算
字节源流1 小时前
【spring Cloud Netflix】OpenFeign组件
java·spring boot·后端
Hi_Lyn1 小时前
MySQL表的增删改查基础版
数据库·mysql
Feng.Lee1 小时前
如何判断数据来源缓存还是数据库
数据库·缓存
Asthenia04121 小时前
Numpy:数组的范围创建/变形/转置/展平
后端
兔子的洋葱圈2 小时前
【django】3 (django路由) 路由配置和反向解析
后端·python·django
Asthenia04122 小时前
NumPy 数组创建方法与区间差异分析
后端