Redis PFCOUNT命令 — 返回HyperLogLog数据结构的基数

当传递单个key调用时,Redis PFCOUNT命令返回由存储在指定key处的HyperLogLog数据结构计算得出的近似基数;如果该变量不存在,则为0

当传递多个键调用时,通过将存储在所有的key处的HyperLogLogs内部合并到临时HyperLogLog中,再返回临时HyperLogLog的近似基数。

可以使用HyperLogLog数据结构,以便仅使用少量恒定的内存就可以对集合中的唯一元素进行计数,每个HyperLogLog明确的只占用12k字节(加上键占用的几个字节)。

所计算得出的集合的基数不是精确的,它有0.81%左右的标准误差。

例如,为了计算一天中执行的所有唯一搜索查询的次数,处理每个查询时,程序都会调用一次PFADD命令。可以随时使用PFCOUNT命令查询唯一查询数。

注意:调用此函数有一下副作用,它可能会修改HyperLogLog,它的最后8个字节用于缓存最新计算的基数。因此从技术上说PFCOUNT是写命令。

可用版本:从2.8.9开始可用
时间复杂度:O(1),O(1)当用单个键调用时,平均用时恒定且非常短。 O(N)当使用多个键调用时,其中N是键的数量。

命令格式

PFCOUNT key [key ...]

返回值

唯一元素的近似数量。

示例

redis> PFADD hll foo bar zap
(integer) 1
redis> PFADD hll zap zap zap
(integer) 0
redis> PFADD hll foo bar
(integer) 0
redis> PFCOUNT hll
(integer) 3
redis> PFADD some-other-hll 1 2 3
(integer) 1
redis> PFCOUNT hll some-other-hll
(integer) 6

性能

当调用PFCOUNT时只传递了单个键,性能极好。即使在理论上处理密集型HyperLogLog非常耗时。 因为PFCOUNT使用缓存来记住上一次计算的基数,这种变化很少改变,因为大多数PFADD操作不会更新任何值。

当传递多个键调用PFCOUNT时,会执行HyperLogLogs的即时合并,这很慢,而且无法缓存合并后的基数,因此当调用PFCOUNT命令传递了多个参数时,耗时比较长,通常需要毫秒级的时间。 不应滥用。

用户应注意,此命令传递单键和多键时。在语义上是不同的,并且性能差别很大。

HyperLogLog形式

Redis HyperLogLogs有两种形式:适用于计数少量元素的稀疏形式(少量非零值),适用于较高基数的密集形式。需要时,Redis会自动从稀疏形式转换为密集形式。

稀疏形式使用经过优化的可变长度编码,以有效地存储大量设置为零的值。密集形式是12288字节的Redis字符串,以便存储16384个6位计数器。需要两种形式的原因是,使用12k(这是密集形式存储要求)对少量基数的数据未达最佳标准。

两种形式都有一个16字节的标头作为前缀,其中包括一个魔术符,一个编码/版本字段和缓存的基数近似值,它以小字节序格式存储(如果HyperLogLog过,估计值无效,则最高有效位为1)。

HyperLogLog是Redis字符串,可以使用GET检索,使用SET重置。对损坏的HyperLogLog调用PFADD,PFCOUNT或PFMERGE命令也不会出错,它将返回一个随机值,但不会影响服务器的稳定性。在大多数情况下,破坏稀疏形式时,服务器会识别出破坏并返回错误。

处理器字大小和字节序与(稀疏或密集)形式无关,因此32位和64位处理器(大字节序或小字节序)使用相同的形式。