参考文章: https://www.xuchuruo.cn/%E7%BB%9F%E8%AE%A1UV%E6%95%B0%E6%8D%AE-HyperLogLog.html
工作中用到了Redis的HyperLogLog,下面就做一个记录
场景:
有一个to C端的H5程序,现需要统计每个页面的用户访问UV(每天共有多少个ip访问的总次数),本来想用redis的set做一个去重然后统计数量。后来发现了HyperLogLog这个数据结构。
为什么要用HyperLogLog(当然会有一定的误差,当对于这种UV统计无所谓)?
Redis对HyperLogLog进行了优化,用了稀疏矩阵存储随着计数的变大,超过了阈值会变成稠密矩阵,才会占用12k存储空间
HyperLogLog产生误差的测试例子如下:
引用一个例子如下:
public static void main(String[] args) {
Jedis jedis = new Jedis();
for (int i = 0; i < 100000; i++) {
jedis.pfadd("userName", "xcr" + i);
}
long total = jedis.pfcount("userName");
System.out.println("100000 --- " + total);
jedis.close();
}
}
运行的数据如下:100000 --- 99415
统计的代码大致流程如下:
1 引入jedis依赖
<!--S=引入redis依赖-->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<!--E=引入redis依赖-->
2 用户进入页面时,获取用户ip,然后通过如下代码插入(可重复执行add,相同会覆盖,不会影响数量)
Jedis jedis = new Jedis();
jedis.pfadd("uv", ip);
3 跑一个job,每隔一段时间获取当前uv数量,并持久化更新到数据库中。
long count = jedis.pfcount("uv");
xxxxxMapper.addOrUpdateTodayUV("uv", count);