Redis 经常使用的数据类型有字符串、列表、哈希、集合和有序集合,但这些类型并不能满足所有的应用场景,因此,Redis 的后续版本不断的扩增其他数据类型来增强 Redis 适用能力。在 Redis 2.8.9 版本中新增了 HyperLogLog 类型。HyperLogLog 并不是一种新的数据结构(实际类型为字符串类型),而是一种基数算法,通过 HyperLogLog 可以利用极小的内存空间完成独立总数的统计,数据集可以是 IP、Email、ID 等。
什么是基数?
-
基数是数据集去重后元素个数
-
HyperLogLog是用来做基数统计的,运用了LogLog的算法
基数举例:
{1,3,5,7,5,7,8} 基数集:{1,3,5,7,8} 基数:5
{1,1,1,1,1,7,1} 基数集:{1,7} 基数:2
HyperLogLog优缺点:
-
优点:在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的、并且是很小的。在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 264 个不同元素的基数。这和计算基数时,元素越多耗费内存就越多的集合形成鲜明对比。
-
缺点:因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。估算的值,可能存在误差。
1、常用命令
下表列出了HyperLogLog 相关命令:
命令 | 描述 |
---|---|
PFADD | 添加指定元素到 HyperLogLog 中。 |
PFCOUNT | 返回给定 HyperLogLog 的基数估算值。 |
PFMERGE | 将多个 HyperLogLog 合并为一个 HyperLogLog |
下面看一组实例演示:假设有 6 个用户(user01-user06),他们分别在当天上午 8 与 9 点访问了某个网站
# 用于向 HyperLogLog 添加元素
# 如果 HyperLogLog 估计的近似基数在 PFADD 命令执行之后出现了变化, 那么命令返回 1 , 否则返回 0
# 如果命令执行时给定的键不存在, 那么程序将先创建一个空的 HyperLogLog 结构, 然后再执行命令
127.0.0.1:6379> pfadd user:uv:2022110208 user01 user02 user03
(integer) 1
127.0.0.1:6379> pfadd user:uv:2022110209 user04 user05
(integer) 1
# PFCOUNT 命令会给出 HyperLogLog 包含的近似基数
# 在计算出基数后, PFCOUNT 会将值存储在 HyperLogLog 中进行缓存,知道下次 PFADD 执行成功前,就都不需要再次进行基数的计算。
127.0.0.1:6379> pfcount user:uv:2022110208
(integer) 3
#重复元素不能添加成功,其基数仍然为3
127.0.0.1:6379> pfadd user:uv:2022110208 user01 user02
(integer) 0
127.0.0.1:6379> pfcount user:uv:2022110208
(integer) 3
#添加新元素值
127.0.0.1:6379> pfadd user:uv:2022110208 user06
(integer) 1
#基数值变为4
127.0.0.1:6379> pfcount user:uv:2022110208
(integer) 4
#统计两个key的基数值
127.0.0.1:6379> pfcount user:uv:2022110208 user:uv:2022110209
(integer) 6
# PFMERGE 将多个 HyperLogLog 合并为一个 HyperLogLog , 合并后的 HyperLogLog 的基数接近于所有输入 HyperLogLog 的并集基数。
#将两个key值合并为一个
127.0.0.1:6379> pfmerge user:uv:2022110208-09 user:uv:2022110208 user:uv:2022110209
OK
#使用合并后key统计基数值
127.0.0.1:6379> pfcount user:uv:2022110208-09
(integer) 6
2、应用场景
HyperLogLog 最典型的应用场景就是统计网站用户月活量UV(浏览用户数量,同一天同一个ip多次访问算一次访问,目的是计数,而不是保存用户),UV 与 PV(页面浏览量) 不同,UV 需要去重,同一个用户一天之内的多次访问只能计数一次。这就要求用户的每一次访问都要带上自身的用户 ID,无论是登陆用户还是未登陆用户都需要一个唯一ID来标识。
当一个网站拥有巨大的用户访问量时,传统的方式,set保存用户的id,可以统计set中元素数量作为标准判断。但如果这种方式保存大量用户id,会占用大量内存,我们的目的是为了计数,而不是去保存id。
我们可以使用 Redis 的 HyperLogLog 来统计网站的 UV (网站独立访客)数据,它提供的去重计数方案,虽说不精确,但 0.81% 的误差足以满足UV 统计的需求。
3、相关说明
-
用于进行基数统计,不是集合,不保存数据,只记录数量而不是具体数据
-
核心是基数统计估算算法,最终数值存在一定误差
-
误差范围:基数统计的结果是一个带有0.81%标准错误的近似值
-
耗空间极小,每个hyperloglog key占用了12k的内存用于标记基数
-
pfadd命令不是一次性分配12k内存使用,会随着基数的增加内存逐渐增大
-
pfmerge命令合并后占用的空间占用的存储空间为12k,无论合并之前数据量多少
原文始发于微信公众号(面试技术):Redis数据类型HyperLogLog
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之家整理,本文链接:https://www.bmabk.com/index.php/post/187124.html