1. 前言
Redis 经常使用的数据类型有字符串、列表、散列、集合和有序集合,但这些类型并不能满足所有的应用场景,因此,Redis 的后续版本不断的扩增其他数据类型来增强 Redis 适用能力。在 Redis 2.8.9 版本中新增了 HyperLogLog 类型。
2. 什么是HyperLoglog
HyperLoglog 是 Redis 重要的数据类型之一,它非常适用于海量数据的计算、统计,其特点是占用空间小,计算速度快。
HyperLoglog 采用了一种基数估计算法,因此,最终得到的结果会存在一定范围的误差(标准误差为 0.81%)。每个 HyperLogLog key 只占用 12 KB 内存,所以理论上可以存储大约2^64
个值,而 set(集合)则是元素越多占用的内存就越多,两者形成了鲜明的对比 。
HyperLoglog 使用起来较为方便,但是其内部原理较为复杂,不建议大家深入研究,只要会用即可。
3. 基数定义
基数定义:一个集合中不重复的元素个数就表示该集合的基数,比如集合 {1,2,3,1,2} ,它的基数集合为 {1,2,3} ,所以基数为 3。HyperLogLog 正是通过基数估计算法来统计输入元素的基数。
HyperLoglog 不会储存元素值本身,因此,它不能像 set 那样,可以返回具体的元素值。HyperLoglog 只记录元素的数量,并使用基数估计算法,快速地计算出集合的基数是多少。
4. 场景应用
HyperLogLog 也有一些特定的使用场景,它最典型的应用场景就是统计网站用户月活量,或者网站页面的 UV(网站独立访客)数据等。
UV 与 PV(页面浏览量) 不同,UV 需要去重,同一个用户一天之内的多次访问只能计数一次。这就要求用户的每一次访问都要带上自身的用户 ID,无论是登陆用户还是未登陆用户都需要一个唯一 ID 来标识。
当一个网站拥有巨大的用户访问量时,我们可以使用 Redis 的 HyperLogLog 来统计网站的 UV (网站独立访客)数据,它提供的去重计数方案,虽说不精确,但 0.81% 的误差足以满足 UV 统计的需求。
5. 常用命令
命令 | 说明 |
---|---|
PFADD key element [element ...] | 添加指定元素到 HyperLogLog key 中。 |
PFCOUNT key [key ...] | 返回指定 HyperLogLog key 的基数估算值。 |
PFMERGE destkey sourcekey [sourcekey ...] | 将多个 HyperLogLog key 合并为一个 key。 |
6. 基本命令
HyperLogLog 提供了三个常用命令,分别是PFADD
、PFCOUNT
和PFMERGE
。
下面看一组实例演示:假设有 6 个用户(user01-user06),他们分别在上午 8 与 9 点访问了网址。
#向指定的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