HyperLogLog应用
一、场景
jim是一个程序员,就职于一家小型互联网公司做Java开发,平时就是使用Redis做缓存、分布式锁使用,突然有一天老板让jim统计一下一个页面的pv和uv,当时的jim是一个小菜鸡(当然,现在也是,哈哈哈)一脸懵逼都不知道pv、uv是什么。
pv:page view的缩写,即页面浏览量,通常是衡量一个网络新闻频道或网站甚至一条网络新闻的热度的主要指标。
uv:unique visitor的简写,是指通过互联网访问、浏览这个网页的自然人,uv需要去重,同一个用户的多次访问只能被记录一次,所以对于未登录的用户,你可能需要把他的IP当做他的唯一标识。
jim小菜鸡明白pv和uv表示的含义后在老板面前立下军令状,a piece of cake。
二、提刀上马和pv、uv大战三百回合--jim被老板上课
jim立下军令状后便开始信誓旦旦的开发了,pv统计可以使用计数器,比如Redis string或者hash结构都可以,string可以用来统计单个页面的的pv,多个页面可以分多个string数据结构的key,也可以使用hash结构,一个Redis key标识pv统计,每一个hash key标识一个页面,每一个hash key对应的value表示该页面的pv值,每次访问使用对应的incrby指令进行自增即可。
uv统计需要去重,那好说啊,Redis set具有去重功能,每当页面被访问时,将用户的唯一标识通过sadd加入到set中,然后通过scard获取set大小。
老板非常看重jim,要亲自review代码,看到pv统计心里窃喜,小伙子没有辜负我的器重,哈哈哈。当老板看到uv统计时气的心脏病差点复发了,但还是忍住了发火并决定亲自给jim上一课。
我们千万级的用户量,一个页面的uv你搞一个set,我要是让你把所有页面都统计一下,是不是需要给你买几台机器搞一个单独的Redis服务啊?120万和125万的uv对我来说有很大却别吗?我需要精准的uv吗?我只是要个差距不是很大的大概值来分析一些问题,所以这个数可以不准确,但不能相差太大,给你个提示,Redis有个高级数据结构HyperLogLog,uv统计可以使用它。
三、jim再战uv--天神(HyperLogLog)相助
HyperLogLog提供不清准的去重方案,不精准的标准误差大概0.81%左右,足够做uv的统计使用。它提供了pfadd可以将用户唯一标识记录下来并通过pfcount来获取用户数。
HyperLogLog还提供了一个神一样的功能pfmerge,用于将多个pf计数值累加在一起组成一个新的pf值,可用于多个页面的uv合并。在Redis集群模式下使用merge可能会报错,原因和哈希槽有关,想要了解的自行百度吧,我不说是因为我也不懂,哈哈哈。
在计数比较小时他的存储空间采用稀疏矩阵存储,空间占用很小。当计数变大,稀疏矩阵占用空间超过阈值时会转化为稠密矩阵,此时占用空间为12k,也就是说如果使用set存储,那么占用空间和存储数据量成正比,而HyperLogLog最大存储空间只需要12k,在uv统计中可谓是四两拨千斤。