深入RedisHyperLogLog

Posted ikct2017

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入RedisHyperLogLog相关的知识,希望对你有一定的参考价值。

HyperLogLog

如果负责开发维护一个大型网站,某天产品经理要每个网页每天的UV数据,对此开发一个统计模块,如何实现?

统计PV很容易,给每个网页一个独立的Redis计数器即可,这个计数器key后缀上当天的日期,来一个请求incrby一次,则可统计出所有的PV数据。

而UV不同,其需要去重,来自同一用户的多次访问只能计数一次,这要求每个请求都要带上用户id,无论是登陆用户还是未登陆用户都需要一个唯一id来标识。

  1. 首先想到的简单方案就是为每个页面提供一个独立的set来存储当天访问过此页面的用户id,来一个请求就sadd进去,通过scard来取出集合大小。

  2. 但是如果页面访问量特别大,就需要很多的空间来统计,而产品经理需要的数据不一定需要特别精确,Redis提供的HyperLogLog数据结构就是用来解决这种统计问题的,其提供不精确的去重统计方案,标准误差是0.81%。

使用方法

HyperLogLog提供两个指令,pfaddpfcount,用法和set的sadd是一样的,来一个用户id就放进去,pfcount的用法与scard用法也是一样的,直接获取计数值。

pf是什么意思?

pf是HyperLogLog这个数据结构的发明人Philippe Flajolet的首字母缩写。

pfmerge适合什么场合用?

HyperLogLog还提供了第三个指令pfmerge,用于将多个pf计数值累加在一起形成一个新的pf值。

例如两个内容差不多的页面数据进行合并,其中UV也要合并,则可以通过pfmerge来处理。

注意事项

HyperLogLog这个数据结构不是免费的,它需要占据一定的存储空间(12k),所以其不适合统计单个用户相关的数据,但相比用set的存储方案,HyperLogLog更完美。

另外,Redis对HyperLogLog的存储做了优化,在计数比较小时采用稀疏矩阵存储,空间占用很小,只有在计数变大,稀疏矩阵占用空间超过阈值才会一次性变为稠密矩阵,进而占用12k的空间。

实现原理

HyperLogLog的使用非常简单,但其实现原理比较复杂。

暂时略

pf的内存占用为什么是12k?

Redis的HyperLogLog视线中用到16384个桶,即2^14,每个桶的maxbits需要6个bits来存储,最大可以标识maxbits=63,于是2^14*6/8 = 12k。

以上是关于深入RedisHyperLogLog的主要内容,如果未能解决你的问题,请参考以下文章

Redis HyperLogLog

Redis入门_下

Redis HyperLogLog

Redis HyperLogLog

深入理解PHP原理之Opcodes

深入解析Android关机