Redis中的HyperLogLog(可用于统计网站访问量)

一般我们评估一个网站的访问量,有几个主要的参数:

  • pv:Page View,网页的浏览量
  • uv:User View,访问的用户

一般来说,pv或者uv的统计,可以自己来做,也可以借助一些第三方的工具,比如cnzz,友盟等。

如果自己实现,pv比较简单,可以直接通过Redis计数器就能实现。但是uv就不一样,uv设计到另外一个问题,去重

我们首先需要在前端给每一个用户生成一个唯一Id,无论是登录用户还是未登录用户,都要有一个唯一id,这个id伴随着请求一起到达后端,在后端我们通过set集合中sadd命令来存储这个id,最后通过scard统计集合大小,进而得到uv数据。

如果是千万级别的uv,需要的存储空间就非常惊人。而且,像uv统计这种,一般也不需要特别精确,800w的uv和803w的uv,其实差别不大。而HyperLogLog可以很好的满足这个要求。

Redis中提供的HperLogLog就是专门用来解决这个问题的,HyperLogLog提供了一套不怎么精确但是够用的去重方案,会有误差,官方给出的误差数据是0.81%,这个精确度,统计UV够用了

HyperLogLog主要提供了两个命令:pfadd和pfcount。

127.0.0.1:6379> pfadd uv u1 u2 u3 
(integer) 1
127.0.0.1:6379> pfcount uv
(integer) 3
127.0.0.1:6379> pfadd uv y u1 u2 u3 u4
(integer) 1
127.0.0.1:6379> pfcount uv
(integer) 5
  • pfadd用来添加记录,类似于sadd,添加过程中,重复的记录会自动去重。pfcount则用来统计数据。
  • 数据量少的时候看不出来误差

在Java中,我们多添加几个元素

public class HyperLogLogTest {
    public static void main(String[] args) {
        Redis redis = new Redis();
        redis.exectu(jedis -> {
            for (int i = 0; i <1000 ; i++) {
                jedis.pfadd("uv","u"+i,"u"+(i+1));
            }
            System.out.println(jedis.pfcount("uv"));//理论值是1001,实际994,可以接受的范围内
        });
    }
}

不精确,但是效率高

除了pfadd和pfcount之外,还有一个命令pfmerge,合并多个统计结果(自动去重多个集合中重复的元素)。

127.0.0.1:6379> pfadd uv1 y u1 u2 u3 u4 o p l
(integer) 1
127.0.0.1:6379> pfmerge uv uv1
OK
127.0.0.1:6379> pfcount uv
(integer) 998
127.0.0.1:6379> 
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐