标签:set 页面 OLE 标识 方案 经理 登陆用户 不同 数据结构
如果负责开发维护一个大型网站,某天产品经理要每个网页每天的UV数据,对此开发一个统计模块,如何实现?
统计PV很容易,给每个网页一个独立的Redis计数器即可,这个计数器key后缀上当天的日期,来一个请求incrby
一次,则可统计出所有的PV数据。
而UV不同,其需要去重,来自同一用户的多次访问只能计数一次,这要求每个请求都要带上用户id,无论是登陆用户还是未登陆用户都需要一个唯一id来标识。
首先想到的简单方案就是为每个页面提供一个独立的set来存储当天访问过此页面的用户id,来一个请求就sadd
进去,通过scard
来取出集合大小。
但是如果页面访问量特别大,就需要很多的空间来统计,而产品经理需要的数据不一定需要特别精确,Redis提供的HyperLogLog数据结构就是用来解决这种统计问题的,其提供不精确的去重统计方案,标准误差是0.81%。
HyperLogLog提供两个指令,pfadd
和pfcount
,用法和set的sadd
是一样的,来一个用户id就放进去,pfcount
的用法与scard
用法也是一样的,直接获取计数值。
pf是HyperLogLog这个数据结构的发明人Philippe Flajolet的首字母缩写。
HyperLogLog还提供了第三个指令pfmerge
,用于将多个pf计数值累加在一起形成一个新的pf值。
例如两个内容差不多的页面数据进行合并,其中UV也要合并,则可以通过pfmerge
来处理。
HyperLogLog这个数据结构不是免费的,它需要占据一定的存储空间(12k),所以其不适合统计单个用户相关的数据,但相比用set的存储方案,HyperLogLog更完美。
另外,Redis对HyperLogLog的存储做了优化,在计数比较小时采用稀疏矩阵存储,空间占用很小,只有在计数变大,稀疏矩阵占用空间超过阈值才会一次性变为稠密矩阵,进而占用12k的空间。
HyperLogLog的使用非常简单,但其实现原理比较复杂。
暂时略
Redis的HyperLogLog视线中用到16384个桶,即2^14,每个桶的maxbits需要6个bits来存储,最大可以标识maxbits=63,于是2^14*6/8 = 12k。
标签:set 页面 OLE 标识 方案 经理 登陆用户 不同 数据结构
原文地址:https://www.cnblogs.com/ikct2017/p/9499228.html