redis高级数据结构---HyperLogLog

业务场景引入

在讲诉HyperLogLog数据结构之前,先讲诉一个业务场景,我们需要记录某个网站的每一个网页的每天的UV数据,然后需要开发一个统计UV的功能模块。该如何实现?

如果是PV数据的话,很简单,每一个页面配置一个单独的redis计数器,按照页面名称_日期作为key,value作为访问次数,每访问一次,就+1。

但是如果是统计UV数据呢,UV需要去重,统计多少人访问过该页面,每个用户的每个ID,无论一天访问多少次,都只能算一次。数据量小的话,实现很简单,可以参考PV的方式,为每个网页设置一个独立的set集合,每访问一次,就将用户的ID扔进set集合,利用set自身的去重性。

ok这样的确没有问题,但是当访问人数据增的时候,上千万,亿级别的时候,set集合就显得有些力不从心了,会需要消耗大量存储空间。

其实对于UV数据,我们并不太在乎他的精确度,举个例子,一个页面访问人数1000万和999万,对于统计来说,差别不是特别的明显。因此,就可以采用更好的解决方案,就是HyperLogLog数据结构。

redis提供HyperLogLog数据结构就是用来解决对精确度要求不是非常高的统计问题的,HyperLogLog提供不精确的去重计数方案,虽然不精确,但是也不是不精确的很离谱,标准误差在0.81%左右。

使用方法

HyperLogLog提供了pfadd,pfcount。根据字面意思很容易理解,pfadd用来增加计数,pfcount用来获取计数,pfadd的用法和set中sadd的用法一样,pfcount和set的scard用法一致。

127.0.0.1:6379> pfadd userlist u1
(integer) 1
127.0.0.1:6379> pfcount userlist
(integer) 1
127.0.0.1:6379> pfadd userlist u2
(integer) 1
127.0.0.1:6379> pfadd userlist u3
(integer) 1
127.0.0.1:6379> pfadd userlist u4
(integer) 1
127.0.0.1:6379> pfadd userlist u5
(integer) 1
127.0.0.1:6379> pfadd userlist u6
(integer) 1
127.0.0.1:6379> pfadd userlist u7
(integer) 1
127.0.0.1:6379> pfadd userlist u8
(integer) 1
127.0.0.1:6379> pfadd userlist u9
(integer) 1
127.0.0.1:6379> pfadd userlist u10
(integer) 1
127.0.0.1:6379> pfcount userlist
(integer) 10
127.0.0.1:6379>

看到这里,心里有点凉,说好的不精确呢,怎么看起来挺精确的啊,好吧,数据量太小,不能说明什么问题。测试下稍微多一点数据。

import redis

client = redis.StrictRedis()
for i in range(1000):
    client.pfadd("userlistnew", "user%d" % i)
    total = client.pfcount("userlistnew")
    if total != i + 1:
        print(total)
        print(i + 1)
        break
/Users/PycharmProjects/demoPy/hyperloglog.py
99
100
Process finished with exit code 0

这里我们加入99个元素之后,加入第100个元素是,出现了不一致的情况,继续加大测试数据。

import redis

client = redis.StrictRedis()
for i in range(100000):
    client.pfadd("userlistnew1", "user%d" % i)

total = client.pfcount("userlistnew1")
print(total)
Users/PycharmProjects/demoPy/hyperloglog.py
99725

插入了10万条,统计到了99725,差了275个,百分比是0.275%,基本满足PV的统计要求,并且也满足了官方的0.81%的误差。

HyperLogLog除了pfadd,pfcount,还提供了pfmerge方法,顾名思义,就是将多个pf值累加在一起,形成一个新的pf值。

注意事项

HyperLogLog这个数据结构不是完全免费的,而是需要占用12kb的内存空间,所以不适合统计单个用户的数据。当用户级别破亿是,存储空间也是相当大的,不过对于set来讲,HyperLogLog的存储几乎不算什么。

当然redis也对HyperLogLog数据结构进行了优化,在计数较小时采用了稀疏矩阵存储,占用空间小,只有当数据量扩大时,才会转化为稠密矩阵,才会占用12kb的存储空间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值