Redis之使用HyperLogLog统计网站UV
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
一句话HyperLogLog用来统计一个很大很大的数据集(海量数据)的基数
Redis在2.8.9版本中添加了HyperLogLog数据结构
1.区分UV和PV:
UV:Unique Vistor 独立访问量 1天内同一个用户多次访问该网站只记录一次
PV:Page View 页面访问量访问一次页面记录一次多次打开这个页面记录多次PV,用来衡量网站的流量
所以PV往往会比UV大UV/PV这个比值可以看出来一个用户访问这个网站是点完一次就走还是在这个网站中浏览了很多页面
2.什么是基数
一个数据集是{1357578}那么这个数据集的基数集就是{13578}这个数据集的基数就是5也就是说数据集去重后的元素个数
3.为什么用HyperLogLog来统计基数而不是用其他的来统计呢节省内存
比如统计1亿个数据的基数
单个HyperLogLog的内存永远小于16kb(内存低的令人发指作为代价其结果可能有一定的误差有小于0.81%的误差这点误差对于UV统计来说是完全可以忽略的比如10000个人差了80个人这点误差可以忽略不计的)
4.实际中如何使用HyperLogLog
HyperLogLog只有三个命令PFADD,PFCOUNT,PFMERGE
1添加元素
Pfadd test1 e1 e2 e3 e4 e5
key你自己选一个名字比如叫test1)后面可以插入1亿个用户id
2统计元素的基数
Pfcount test1
3现在如果有两个key都是HyperLogLog类型的将这两个key合并一下(合并30天的UV就可以得到一个月的UV,关键是就算把365天一年的UV合并起来内存大小都不会超过16kb)
@Test
public void testHyperLogLog()
{
String[] users=new String[1000000];
for(int i=0;i<=1000000;i++)
{
users[i]="user_"+i;
stringRedisTemplate.opsForHyperLogLog().add("test1",user[i]);
}
System.out.println(stringRedisTemplate.opsForHyperLogLog().size("test1"));
}
插入了100 0000一百万条数据最后先是size=997593 有一定的误差但是误差不大然后内存大小为14KB确实没有超过16KB
合并多个HyperLogLog成1个HyperLogLog
下面合并test1test2test3 3个HyperLogLog成一个HyperLogLog新HyperLogLog叫做test4
stringRedisTemplate.opsForHyperLogLog().add("test1","ip1","ip2","ip3");
stringRedisTemplate.opsForHyperLogLog().add("test2","ip1","ip2","ip3","ip4","ip5");
stringRedisTemplate.opsForHyperLogLog().add("test3","ip4","ip5","ip6","ip7","ip8");
stringRedisTemplate.opsForHyperLogLog().union("test4","test1","test2","test3");
最终如果想要统计每一天的UV,可以将日期作为key这一天访问网站的客户端ip地址作为value