Redis hyperloglog去重复统计
就比如一个大型的网站会少不了大量的用户访问,就比如天猫的uv访问统计,一个用户一天内访问多次顶多算一次uv;淘宝、天猫首页的uv平均每天是1~1.5亿左右;,每天存1.5亿个用户的ip,访问者来了先去查是否存在,不存在则写入,那么这个存储得占多大空间?另外统计的读取速度又能保证达到预期吗?
这里可能想到的是哈希,redis 的hset;
比如
//今天ip192.168.1.1用户访问1次 127.0.0.1:6379> hset today1 192.168.1.1 1 (integer) 1 127.0.0.1:6379> hset today1 192.168.1.2 1 (integer) 1 127.0.0.1:6379> hset today1 192.168.1.3 1 (integer) 1 127.0.0.1:6379> hset today1 192.168.1.5 1 (integer) 1 127.0.0.1:6379> hgetall today1 1) "192.168.1.1" 2) "1" 3) "192.168.1.2" 4) "1" 5) "192.168.1.3" 6) "1" 7) "192.168.1.5" 8) "1" 127.0.0.1:6379>
hash 命令 keyday,ip,1次
按照ipv4的结构来说明,每个ipv4的地址最多是15个字节(ip=”192.168.1.1“,最多xxx.xxx.xxx.xxx),某一天的1.5亿*15个字节=2G,一个月60G,redis还咋玩。
这里hyperloglog就用上了!
Redis 在 2.8.9 版本添加了 HyperLogLog 结构。
Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。
在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基 数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。
但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。
为什么是12Kb?
每个桶取6位,16384*6➗8=12kb,每个桶有6位,最大全部都是1,值就是63。
通过牺牲准确率来换取空间,误差仅仅是0.81%左右(来自官方说明),对于不要求绝对精准率下的场景可以使用,因为概率算法不直接存储数据本身,通过一定的概率统计方法预估基数值,同时保证误差在一定范围内,由于又不存储数据故此可以大大节约内存。
操作
127.0.0.1:6379> PFADD taobao:uv 111 112 113 (integer) 1 127.0.0.1:6379> PFCOUNT taobao:uv (integer) 3 127.0.0.1:6379> PFADD taobao:uv 111 112 113 114 115 (integer) 1 127.0.0.1:6379> PFADD taobao:uv 111 112 113 114 115 (integer) 0 127.0.0.1:6379> PFADD taobao:uv 116 (integer) 1 127.0.0.1:6379> del taobao:uv (integer) 1 127.0.0.1:6379>
127.0.0.1:6379> PFADD jd:uv1 1 2 3 (integer) 1 127.0.0.1:6379> PFADD jd:uv2 1 2 3 4 5 (integer) 1 127.0.0.1:6379> PFADD jd:uv1 2 (integer) 0 127.0.0.1:6379> PFCOUNT jd:uv1 (integer) 3 127.0.0.1:6379> PFMERGE result jd:uv1 jd:uv2 OK 127.0.0.1:6379> PFCOUNT result (integer) 5 127.0.0.1:6379>
应用场景
说明:
- 基数不大,数据量不大就用不上,会有点大材小用浪费空间
- 有局限性,就是只能统计基数数量,而没办法去知道具体的内容是什么
- 和bitmap相比,属于两种特定统计情况,简单来说,HyperLogLog 去重比 bitmap 方便很多
- 一般可以bitmap和hyperloglog配合使用,bitmap标识哪些用户活跃,hyperloglog计数
一般使用:
- 统计注册 IP 数
- 统计每日访问 IP 数
- 统计页面实时 UV 数
- 统计在线用户数
- 统计用户每天搜索不同词条的个数