Redis HyperLoglog基数统计

1年前 (2024-04-27)
Redis 经常使用的数据类型有字符串、列表、散列、和有序,但这些类型并不能满足所有的应用场景,因此,Redis 的后续版本不断的扩增其他数据类型来增强 Redis 适用能力。在 Redis 2.8.9 版本中新增了 HyperLogLog 类型。

什么是HyperLoglog

HyperLoglog 是 Redis 重要的数据类型之一,它非常适用于海量数据的计算、统计,其特点是占用空间小,计算速度快。

HyperLoglog 采用了一种基数估计算法,因此,最终得到的结果会存在一定范围的误差(标准误差为 0.81%)。每个 HyperLogLog key 只占用 12 KB 内存,所以理论上可以存储大约2^64个值,而 set()则是元素越多占用的内存就越多,两者形成了鲜明的对比 。

HyperLoglog 使用起来较为方便,但是其内部原理较为复杂,不建议大家深入研究,只要会用即可。

基数定义

基数定义:一个中不重复的元素个数就表示该的基数,比如 {1,2,3,1,2} ,它的基数为 {1,2,3} ,所以基数为 3。HyperLogLog 正是通过基数估计算法来统计输入元素的基数。

HyperLoglog 不会储存元素值本身,因此,它不能像 set 那样,可以返回具体的元素值。HyperLoglog 只记录元素的数量,并使用基数估计算法,快速地计算出的基数是多少。

场景应用

HyperLogLog 也有一些特定的使用场景,它最典型的应用场景就是统计网站用户月活量,或者网站页面的 UV(网站独立访客)数据等。

UV 与 PV(页面浏览量) 不同,UV 需要去重,同一个用户之内的多次访问只能计数一次。这就要求用户的每一次访问都要带上自身的用户 ID,无论是登陆用户还是未登陆用户都需要一个 ID 来标识。

当一个网站拥有巨大的用户访问量时,我们可以使用 Redis 的 HyperLogLog 来统计网站的 UV (网站独立访客)数据,它提供的去重计数方案,虽说不精确,但 0.81% 的误差足以满足 UV 统计的需求。

常用令

HyperLoglog令

说明

PFADD key element [element ...]

添加指定元素到 HyperLogLog key 中。

PFCOUNT key [key ...]

返回指定 HyperLogLog key 的基数估算值。

PFMERGE destkey sourcekey [sourcekey ...]

将多个 HyperLogLog key 并为一个 key。

 

基本令

HyperLogLog 提供了三个常用令,分别是PFADDPFCOUNTPFMERGE

下面看一组实例演示:假设有 6 个用户(user01-user06),他们分别在上午 8 与 9 点访问了www.biancheng网站站点" rel="nofollow" />

#向指定的key中添加用户

127.0.0.1:6379> PFADD user:uv:2021011308 user01 user02 user03

(integer) 1

#向指定的key中添加用户

127.0.0.1:6379> PFADD user:uv:2021011309 user04 user05

(integer) 1

#统计基数值

127.0.0.1:6379> PFCOUNT user:uv:2021011308

(integer) 3

#重复元素不能添加成功,其基数仍然为3

127.0.0.1:6379> PFADD user:uv:2021011308 user01 user02

(integer) 0

127.0.0.1:6379> PFCOUNT user:uv:2021011308

(integer) 3

#添加新元素值

127.0.0.1:6379> PFADD user:uv:2021011308 user06

(integer) 1

#基数值变为4

127.0.0.1:6379> PFCOUNT user:uv:2021011308

(integer) 4

#统计两个key的基数值

127.0.0.1:6379> PFCOUNT user:uv:2021011308 user:uv:2021011309

(integer) 6

#将两个key值并为一个

127.0.0.1:6379> PFMERGE user:uv:2021011308-09 user:uv:2021011308 user:uv:2021011309

OK

#使用并后key统计基数值

127.0.0.1:6379> PFCOUNT user:uv:2021011308-09

(integer) 6

在线练习工具:https://try.redis.io/

查看更多令:https://redis.io/commands