需求分析
现在一个网站需要统计访问量
那么就会需要两个关键的数据:
网站的浏览量:Page View ,下面简称PV
网站的用户访问数量:User View,下面简称UV
简单的实现PV与UV统计
-
PV统计
在Redis的String类型中,提供了一个API为incr key
,可以为一个key的value做自增操作,每次调用则自增1。
我们可以将pv视作key,每次网站被点击就自增1,就可以简单的实现PV的统计了。
-
UV统计
Redis还有一个Set的数据结构,可以轻松的实现去重的操作,通过sadd key element
指令,将uv视作key,不同的用户视作element,每当一个新用户进入网站时,则往set集合中添加一个userId。在需要统计的时候通过scard key
指令(时间复杂度为O(1)),则可以得到网站的用户访问数量了.
缺点:当用户量暴增的时候,由于set集合里面存储的是元素值,会耗费大量的空间,而这个数据本身是允许有容错的。得不偿失
为此,Redis提供了另外一种数据结构:HypeLogLog
HypeLogLog
HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。
在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。
它提供了几个指令,但是解决UV这个问题,我们只需要用到其中的两个指令即可
pfadd key element|element
统计
pfcount key
下面在Java中模拟数据进行测试,发现结果的准确率是很高的。
package com.xjm.redis;
/**
* 使用Redis的HyperLogLog统计用户访问量Page View和访问用户数User View
*/
public class CountPvAndUv {
public static void main(String[] args) {
Redis redis = new Redis();
redis.exeute(jedis -> {
for (int i = 0; i < 2000; i++) {
//key为uv,value每次放2个,一个是当前的i,一个是下一个i值,那么下次循环就会产生重复值了
jedis.pfadd("uv","u"+i,"u"+(i+1));
}
long uv = jedis.pfcount("uv");
System.out.println(uv);
});
}
}

网友评论