Redis如何使用HyperLogLog的实现

目录
  • 1. 概述
  • 2. 什么是基数?
  • 3. 命令
    • 3.1 PFADD
    • 3.2 PFCOUNT
    • 3.3 PFMERGE

1. 概述

Redis 在 2.8.9 版本添加了 HyperLogLog 数据结构,用来做基数统计,其优点是在输入元素的数量非常大时,计算基数所需的空间比较小并且一般比较恒定。

在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存就可以计算接近 2^64 个不同元素的基数。这和计算基数时,元素越多耗费内存越多的集合形成鲜明对比。但是,因为 HyperLogLog 只会根据输入元素来计算基数,并不会储存输入元素本身,所以 HyperLogLog 不能像集合那样能返回输入的各个元素。

2. 什么是基数?

比如数据集 {1, 3, 5, 7, 5, 7, 8}, 那么这个数据集的基数集为 {1, 3, 5 ,7, 8}, 基数(不重复元素)为5。基数估计就是在误差可接受的范围内,快速计算基数。

3. 命令

HyperLogLog 目前只支持 3 个命令,PFADD、PFCOUNT、PFMERGE。我们先来逐一介绍一下。

3.1 PFADD

最早可用版本:2.8.9。时间复杂度:O(1)。

PFADD 命令可以将元素(可以指定多个元素)添加到 HyperLogLog 数据结构中,存储到第一个参数 key 指定的键中。命令执行之后,如果基数估计(评估的元素个数)发生变化就返回 1,否则返回 0。如果指定的 key 不存在,那么就创建一个空的 HyperLogLog 数据结构(即,指定字符串长度以及编码的 Redis String)。也可以调用不指定元素参数而只指定键的命令。如果键存在,不执行任何操作并返回 0;如果键不存在,则会创建一个新的 HyperLogLog 数据结并且返回 1。本质上只是创建一个新的 HyperLogLog 数据结,不存储任何元素。

(1) 语法格式:

PFADD key element [element ...]

(2) 返回值:

整型,如果至少有个元素被添加返回 1,否则返回 0。

(3) Example:

127.0.0.1:6379> PFADD hll a b c d e f g
(integer) 1
127.0.0.1:6379> pfcount hll
(integer) 7

3.2 PFCOUNT

最早可用版本:2.8.9。时间复杂度:O(1),对于多个比较大的key的时间复杂度是O(N)。

PFCOUNT 命令返回指定 HyperLogLog 的基数估算值(元素个数)。对于单个键,该命令返回的是该键的基数估算值,如果该键不存在,则返回 0。对于多个键,返回的是多个 HyperLogLog 并集的基数估算值,通过将多个 HyperLogLog 合并为一个临时的 HyperLogLog 计算基数估算值。HyperLogLog 只使用很少且恒定的内存来计算集合的不同元素个数。每个 HyperLogLog 只用 12K 加上键本身的几个字节。

(1) 语法格式:

PFCOUNT key [key ...]

(2) 返回值:

整数,返回指定 HyperLogLog 的基数估算值,如果多个 HyperLogLog 则返回并集的基数估算值。

(3) Example:

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

(4) 限制:

HyperLogLog 返回的结果并不精确,错误率大概在 0.81% 左右。

该命令会修改 HyperLogLog,会使用8个字节来存储上一次计算的基数。所以,从技术角度来讲,PFCOUNT 是一个写命令。

(5) 性能问题

即使理论上处理一个密集型 HyperLogLog 需要花费较长时间,但是当只指定一个键时,PFCOUNT 命令仍然具有很高的性能。这是因为 PFCOUNT 会缓存上一次计算的基数,并且这个基数并不会一直变动,因为 PFADD 命令大多数情况下不会更新寄存器。所以才可以达到每秒上百次请求的效果。

当使用 PFCOUNT 命令处理多个键时,会对 HyperLogLog 进行合并操作,这一步非常耗时,更重要的是通过计算出来的并集的基数是不能缓存的。因此当使用多个键时,PFCOUNT 可能需要花费一些时间(毫秒数量级),因此不建议过多使用。

需要注意的是,该命令的单键和多键执行语义是不同的并且具有不同的性能。不建议过多使用多键执行语义。

3.3 PFMERGE

最早可用版本:2.8.9。时间复杂度:O(N),N是要合并的HyperLogLog的数量。

PFMERGE 命令将多个 HyperLogLog 合并为一个 HyperLogLog。合并后的 HyperLogLog 的基数估算值是通过对所有给定 HyperLogLog 进行并集计算得出的。计算完的结果保存到指定的键中。

语法格式:

PFMERGE destkey sourcekey [sourcekey ...]

返回值:

返回 OK。

Example:

127.0.0.1:6379> PFADD hll1 foo bar zap a
(integer) 1
127.0.0.1:6379> PFADD hll2 a b c foo
(integer) 1
127.0.0.1:6379> PFMERGE hll3 hll1 hll2
OK
127.0.0.1:6379> PFCOUNT hll3
(integer) 6

到此这篇关于Redis如何使用HyperLogLog的实现的文章就介绍到这了,更多相关Redis HyperLogLog内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Redis高级数据类型Hyperloglog、Bitmap的使用

    前言 很多小伙伴在面试中都会被问道 Redis的常用数据结构有哪些? 可能很大一部分回答都是 string.hash.list.set.zset.当然啦,这个答案肯定是没有错的,但是相信这个答案,面试官已经听的耳朵都起茧了. 本身我们选择的这个行业竞争就极强,学历拼不过难道还要知识都拼不过吗??? 希望进来的小伙伴能好好看完这篇文章,也希望你以后的回答能是 常用的数据结构有string.hash.list.set.zset,但我平时可能还会用到 Hyperloglog和Bitmap.相信面试官听

  • Redis特殊数据类型HyperLogLog基数统计算法讲解

    目录 Redis HyperLogLog基数统计 一.pfadd 二.pfcount 三.pfmerge Redis HyperLogLog基数统计 HyperLogLog 是用来做基数统计的算法. 先了解下什么是基数. 比如数据集{1, 3, 5, 7, 5, 7, 8},那么这个数据集的基数集为{1, 3, 5 ,7, 8},基数(不重复元素)为5. 如果,现在需要统计一下网页的UV,那么就会涉及到去重了,这种场景就很适合用HyperLogLog. 这不就是set集合嘛?我用set来得出不重

  • Redis中3种特殊的数据类型(BitMap、Geo和HyperLogLog)

    前言 Reids 在 Web 应用的开发中使用非常广泛,几乎所有的后端技术都会有涉及到 Redis 的使用.Redis 种除了常见的字符串 String.字典 Hash.列表 List.集合 Set.有序集合 SortedSet 等等之外,还有一些不常用的数据类型,这里着重介绍三个.下面话不多说了,来一起看看详细的介绍吧. BitMap BitMap 就是通过一个 bit 位来表示某个元素对应的值或者状态, 其中的 key 就是对应元素本身,实际上底层也是通过对字符串的操作来实现.Redis 从

  • Redis如何使用HyperLogLog的实现

    目录 1. 概述 2. 什么是基数? 3. 命令 3.1 PFADD 3.2 PFCOUNT 3.3 PFMERGE 1. 概述 Redis 在 2.8.9 版本添加了 HyperLogLog 数据结构,用来做基数统计,其优点是在输入元素的数量非常大时,计算基数所需的空间比较小并且一般比较恒定. 在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存就可以计算接近 2^64 个不同元素的基数.这和计算基数时,元素越多耗费内存越多的集合形成鲜明对比.但是,因为 Hype

  • Redis精确去重计数方法(咆哮位图)

    前言 如果要统计一篇文章的阅读量,可以直接使用 Redis 的 incr 指令来完成.如果要求阅读量必须按用户去重,那就可以使用 set 来记录阅读了这篇文章的所有用户 id,获取 set 集合的长度就是去重阅读量.但是如果爆款文章阅读量太大,set 会浪费太多存储空间.这时候我们就要使用 Redis 提供的 HyperLogLog 数据结构来代替 set,它只会占用最多 12k 的存储空间就可以完成海量的去重统计.但是它牺牲了准确度,它是模糊计数,误差率约为 0.81%. 那么有没有一种不怎么

  • Redis中HyperLogLog的使用详情

    目录 前言 添加元素 前言 HyperLogLog ,基数统计: 那什么是基数? 比如有两个数组 数组A = [1,2,3,4,5]; 数组B = [3,4,5,6,7]; 这时候基数就是 [1,2,3,4,5,6,7],总共有7个数: 就是去重之后的数据: HyperLogLog 就是用来做去重复统计的: bitmap 在做统计时,虽然使用的是 bit 来做记录,已经很节省空间了: 但是在随着数据量快速增长的情况下,bitmap 也是很占内存空间的: 而 HyperLogLog 就不同了,Hy

  • redis简介_动力节点Java学院整理

    Redis是一个开源的,先进的 key-value 存储可用于构建高性能,可扩展的 Web 应用程序的解决方案.Redis官方网网站是:http://www.redis.io/,如下: Redis 有三个主要使其有别于其它很多竞争对手的特点: Redis是完全在内存中保存数据的数据库,使用磁盘只是为了持久性目的: Redis相比许多键值数据存储系统有相对丰富的数据类型: Redis可以将数据复制到任意数量的从服务器中: Redis优点 异常快速 : Redis是非常快的,每秒可以执行大约110

  • 详解在Redis在Centos7上的安装部署

    Redis是一种高级key-value数据库.它跟memcached类似,不过数据可以持久化,而且支持的数据类型很丰富.有字符串,链表,集 合和有序集合.支持在服务器端计算集合的并,交和补集(difference)等,还支持多种排序功能.所以Redis也可以被看成是一个数据结构服务器. Redis的所有数据都是保存在内存中(效率高),然后不定期的通过异步方式保存到磁盘上(这称为"半持久化模式"):也可以把每一次数据变化都写入到一个append only file(aof)里面(这称为&

  • Redis实现唯一计数的3种方法分享

    唯一计数是网站系统中十分常见的一个功能特性,例如网站需要统计每天访问的人数 unique visitor (也就是 UV).计数问题很常见,但解决起来可能十分复杂:一是需要计数的量可能很大,比如大型的站点每天有数百万的人访问,数据量相当大:二是通常还希望扩展计数的维度,比如除了需要每天的 UV,还想知道每周或每月的 UV,这样导致计算十分复杂. 在关系数据库存储的系统里,实现唯一计数的方法就是 select count(distinct <item_id>),它十分简单,但是如果数据量很大,这

  • Redis 的各项功能主要解决了什么问题

    先看一下Redis是一个什么东西.官方简介解释到: Redis是一个基于BSD开源的项目,是一个把结构化的数据放在内存中的一个存储系统,你可以把它作为数据库,缓存和消息中间件来使用.同时支持strings,lists,hashes,sets,sorted sets,bitmaps,hyperloglogs和geospatial indexes等数据类型.它还内建了复制,lua脚本,LRU,事务等功能,通过redis sentinel实现高可用,通过redis cluster实现了自动分片.以及事

随机推荐