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统计后的结果与实际结果存在误差,但是在数据量很大的情况下,这点误差误伤大雅。:

相关推荐
Python私教2 小时前
model中能定义字段声明不存储到数据库吗
数据库·oracle
Estar.Lee3 小时前
查手机号归属地免费API接口教程
android·网络·后端·网络协议·tcp/ip·oneapi
BestandW1shEs4 小时前
谈谈Mysql的常见基础问题
数据库·mysql
重生之Java开发工程师4 小时前
MySQL中的CAST类型转换函数
数据库·sql·mysql
教练、我想打篮球4 小时前
66 mysql 的 表自增长锁
数据库·mysql
Ljw...4 小时前
表的操作(MySQL)
数据库·mysql·表的操作
哥谭居民00014 小时前
MySQL的权限管理机制--授权表
数据库
2401_857610034 小时前
SpringBoot社团管理:安全与维护
spring boot·后端·安全
wqq_9922502774 小时前
ssm旅游推荐系统的设计与开发
数据库·旅游