一般我们评估一个网站的访问量,有几个主要的参数:PV(Page View)
网页的浏览量、UV(User View)
访问的用户量。有很多第三方工具可以统计,如 cnzz,友盟等。如果自己实现的话,PV 比较简单,可以直接通过 Redis 计数器实现。但是 UV 就不一样,UV 涉及到去重的问题。
常规思路:我们首先需要在前端给每一个用户生成一个唯一 id,无论是登录用户还是未登录用户都需要,这个 id 伴随着请求一起到达后端,在后端我们可以通过 Set
数据结构中的 sadd
命令来存储这个 id,最后通过 scard
统计集合大小,进而得出 UV 数据。
按上述思路,如果是千万级别的 UV,需要的存储空间就非常惊人,用 Set 就不是很合适了。一般来说像 UV 统计这种,不需要特别精确,比如 800W 和 803W 的 UV,其实差别不大。因此,我们可以使用 HyperLogLog
来高效的实现。
Redis 中提供的 HyperLogLog 就是专门用来解决上述问题的,HyperLogLog 提供了一套不怎么精确但是够用的去重方案,会有误差,官方给出的误差数据是 0.81%
,这对于 UV 的统计够用了。
HyperLogLog 主要提供了以下命令:
pfadd
:用来添加记录,类似于 sadd ,添加过程中,重复的记录会自动去重。pfcount
:则用来统计数据。pfmerge
:合并多个统计结果,在合并的过程中,会自动去重多个集合中重复的元素。数据量少的时候看不出来误差,我们在 Java 中多添加几个元素:
public class HyperLogLogTest { @Test public void testHyperLogLog() { Redis redis = new Redis(); redis.execute(jedis -> { for (int i = 0; i < 1000; i++) { // 重复加入数据,理论值上总数为 1001 jedis.pfadd("uv", "u" + i, "u" + (i + 1)); } long uv = jedis.pfcount("uv"); System.out.println(uv); }); } }
理论值上总数为 1001,实际打印出来 994,有误差,但是在可以接受的范围内。
最新评论: