前言
HyperLogLog ,基数统计;
那什么是基数?
比如有两个数组
数组A = [1,2,3,4,5];
数组B = [3,4,5,6,7];
这时候基数就是 [1,2,3,4,5,6,7],总共有7个数;
就是去重之后的数据;
HyperLogLog 就是用来做去重复统计的;
bitmap 在做统计时,虽然使用的是 bit 来做记录,已经很节省空间了;
但是在随着数据量快速增长的情况下,bitmap 也是很占内存空间的;
而 HyperLogLog 就不同了,HyperLogLog 的每个 key 只占用 12kb 的内存,
就可以统计 2的64 次方个基数;
而且不会随着数据量的增多而变大,就是固定的 12kb;
这是因为 HyperLogLog 每次只会根据添加的数据去计算基数,而不保存添加的数据本身;
但这也造成了一个问题,就是 HyperLogLog 基数统计的准确率不是100%,会有 0.81% 的误差;
但对于亿级数据的统计,这点误差似乎可以忽略不计;
同样的,bitmap 记录数据本身,它的计算是精确的;
所有,也可以说 HyperLogLog 是一种概率计算,但是误差是很小的。
HyperLogLog 的使用也非常简单,就3个操作api
添加元素
1 | pfadd key value [value ...] |
1 2 3 | pfadd 20220628:uv ip1 ip2 ip3 pfadd 20220629:uv ip1 ip2 ip3 ip4 ip5 pfadd 20220630:uv ip2 ip4 ip5 ip6 ip7 ip8 |
重复数据不会被保存,返回的是0
1 2 3 4 | > pfadd 20220628:uv ip1 ip2 ip3 1 > pfadd 20220628:uv ip1 ip2 ip3 0 |
- 获取 HyperLogLog 的基数估算值
1 | PFCOUNT key [key ...] |
1 2 | > pfcount 20220628:uv 20220629:uv 5 |
合并得出的不会被储存,使用之后就会被删掉
- 合并多个key
1 | pfmerge destkey key [key ...] |
1 2 | > pfmerge result 20220628:uv 20220629:uv 20220630:uv OK |
pfmerge 合并多个key后,会生成一条 result 数据
然后再对 result 做 pfcount 操作
1 2 | > pfcount result 8 |
这时候拿到的值就是 上面3个key 计算出来的基数。
HyperLogLog 在 spring 里的使用也非常简单,
pfadd 对应的是 .add() 操作;
pfcount 对应的是 .size() 操作;
pfmerge 对应的是 .union() 操作;
下面是使用的 Demo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | import org.junit.jupiter.api.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.redis.core.HyperLogLogOperations; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.test.context.junit4.SpringRunner; import javax.annotation.Resource; @SpringBootTest @RunWith (SpringRunner. class ) class RedisTest { @Resource private RedisTemplate redisTemplate; @Test void hyperLogLogTest() { HyperLogLogOperations hyperLogLogOperations = redisTemplate.opsForHyperLogLog(); // 添加元素 Long add = hyperLogLogOperations.add( "20220628:uv" , "ip1" , "ip2" , "ip3" ); System.out.println( "add : " + add); hyperLogLogOperations.add( "20220629:uv" , "ip1" , "ip2" , "ip3" , "ip4" , "ip5" ); hyperLogLogOperations.add( "20220630:uv" , "ip2" , "ip4" , "ip5" , "ip6" , "ip7" , "ip8" ); // 获取元素基数 Long size = hyperLogLogOperations.size( "20220628:uv" , "20220629:uv" ); System.out.println( "size : " + size); // 合并多个元素 Long result = hyperLogLogOperations.union( "unionResult" , "20220628:uv" , "20220629:uv" , "20220630:uv" ); System.out.println( "result : " + result); Long unionResult = hyperLogLogOperations.size( "unionResult" ); System.out.println( "unionResult : " + unionResult); } } |
到此这篇关于Redis中HyperLogLog的使用详情的文章就介绍到这了,更多相关RedisH yperLogLog内容请搜索IT俱乐部以前的文章或继续浏览下面的相关文章希望大家以后多多支持IT俱乐部!