统计网页UV
如果你的页面访问量非常大,比如一个爆款页面几千万的 UV,你需要一个很大的 set
集合来统计,这就非常浪费空间。如果这样的页面很多,那所需要的存储空间是惊人的。为这样一个去重功能就耗费这样多的存储空间,不值得。可以使用HyperLogLog
。
HyperLogLog
提供了两个指令 pfadd
和 pfcount
,根据字面意义很好理解,一个是增加计数,一个是获取计数。pfadd
用法和 set
集合的 sadd
是一样的,来一个用户 ID,就将用户 ID 塞进去就是。pfcount
和 scard
用法是一样的,直接获取计数值。
127.0.0.1:6379> pfadd webpage user1
(integer) 1
127.0.0.1:6379> pfcount webpage
(integer) 1
127.0.0.1:6379> pfadd webpage user2
(integer) 1
127.0.0.1:6379> pfcount webpage
(integer) 2
127.0.0.1:6379> pfadd webpage user3 user4 user5 user6 user7 user8 user9 user10
(integer) 1
127.0.0.1:6379> pfcount webpage
(integer) 10
@Autowired
private RedisTemplate redisTemplate;
@Test
public void pfTest() {
long start=System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
pfadd("webpage", "user"+i);
}
Long total = pfcount("webpage");
System.out.println("\r\n");
System.out.printf("%d %d\n",100000, total);
System.out.println("\r\n"+(System.currentTimeMillis()-start)+"\r\n");
}
private List<Long> pfadd(final String key, Object ...value){
HyperLogLogOperations<Serializable, Object> operations=redisTemplate.opsForHyperLogLog();
List<Long> longs=new ArrayList<>();
for (int i = 0; i < value.length; i++) {
Long add = operations.add(key, value[i]);
longs.add(add);
}
return longs;
}
private Long pfcount(final String key){
HyperLogLogOperations<Serializable, Object> operations=redisTemplate.opsForHyperLogLog();
Long size = operations.size(key);
return size;
}
结果如下,差205个,0.205%,误差率不是算太高,再跑一次代码,结果还是一样,说明HLL
有去重的功能
100000 99795
8963