HyperLogLog 使用及其算法原理详细讲解

目录一、简介二、命令2.1 PFADD key element [element …]2.2 PFCOUNT key [key …]2.3 PFMERGE destkey sourcekey [sourcekey …]三、原理3.1 伯努利试验3.2 估值优化3.3 HyperLogLog的实现3.4 代码实现-BernoulliExperiment(伯努利试验)3.5 代码实现-HyperLogLog一、简介首先抛出一个业务问题:假设产品经理让你设计一
摘要由CSDN通过智能技术生成

本文已收录于专栏

❤️《Redis之大厂必备技能包》❤️

欢迎各位关注、三连博主的文章及专栏,全套Redis学习资料,大厂必备技能!


目录

一、简介

二、命令

2.1 PFADD key element [element …]

2.2 PFCOUNT key [key …]

2.3 PFMERGE destkey sourcekey [sourcekey …]

三、原理

3.1 伯努利试验

3.2 估值优化

3.3 HyperLogLog的实现

3.4 代码实现-BernoulliExperiment(伯努利试验)

3.5 代码实现-HyperLogLog


一、简介

首先抛出一个业务问题:
假设产品经理让你设计一个模块,来统计PV(Page View页面的访问量),那么你会怎么做?
我想很多人对于PV(Page View页面的访问量)的统计会很快的想到使用Redis的incr、incrby指令,给每个网页配置一个独立Redis计数器就可以了,把这个技术区的key后缀加上当它的日期,这样一个请求过来,就可以通过执行incr、incrby指令统计所有PV。

此时当你完成这个需求后,产品经理又让你设计一个模块,统计UV(Unique Visitor,独立访客),那么你又会怎么做呢?
UV与PV不一样,UV需要根据用户ID去重,如果用户没有ID我们可能需要考虑使用用户访问的IP或者其他前端穿过了的唯一标志来区分,此时你可能会想到使用如下的方案来统计UV。

  1. 存储在MySQL数据库表中,使用distinct count计算不重复的个数
  2. 使用Redis的set、hash、bitmaps等数据结构来存储,比如使用set,我们可以使用用户ID,通过sadd加入set集合即可

但是上面的两张方案都存在两个比较大的问题:

  1. 随着数据量的增加,存储数据的空间占用越来越大,对于非常大的页面的UV统计,基本不合实际
  2. 统计的性能比较慢,虽然可以通过异步方式统计,但是性能并不理想

因此针对UV的统计,我们将会考虑使用Redis的新数据类型HyperLogLog.
HyperLogLog是用来做基数统计的算法,它提供不精确的去重计数方案(这个不精确并不是非常不精确),标准误差是0.81%,对于UV这种统计来说这样的误差范围是被允许的。HyperLogLog的优点在于,输入元素的数量或者体积非常大时,基数计算的存储空间是固定的。在Redis中,每个HyperLogLog键只需要花费12KB内存,就可以计算接近2^64个不同的基数。
但是:HyperLogLog只能统计基数的大小(也就是数据集的大小,集合的个数),他不能存储元素的本身,不能向set集合那样存储元素本身,也就是说无法返回元素。

HyperLogLog指令都是pf(PF)开头,这是因为HyperLogLog的发明人是Philippe Flajolet,pf是他的名字的首字母缩写。

二、命令

2.1 PFADD key element [element …]

将任意数量的元素添加到指定的 HyperLogLog 里面,当PFADD key element [element …]指令执行时,如果HyperLogLog的估计近似基数在命令执行之后出现了变化,那么命令返回1,否则返回0,如果HyperLogLog命令执行时给定的键不存在,那么程序将先创建一个空的HyperLogLog结构,再执行命令。
该命令可以只给定key不给element,这种以方式被调用时:

  • 如果给定的键存在且已经是一个HyperLogLog,那么这种调用不会产生任何效果
  • 如果给定的键不存在,那么命令会闯进一个空的HyperLogLog,并且给客户端返回1

返回值:
如果HyperLogLog数据结构内部存储的数据被修改了,那么返回1,否则返回0

时间复杂度:
O(1)

使用示例:

image.png

2.2 PFCOUNT key [key …]

PFCOUNT 指令后面可以跟多个key,当PFCOUNT key [key …]命令作用于单个键时,返回存储在给定键的HyperLogLog的近似基数,如果键不存在,则返回0;当PFCOUNT key [key …]命令作用于多个键时,返回所给定HyperLogLog的并集的近似基数,这个近似基数是通过将索引给定HyperLogLog合并至一个临时HyperLogLog来计算得出的。

返回值:
返回给定HyperLogLog包含的唯一元素的近似数量的整数值

时间复杂度:
当命令作用于单个HyperLogLog时,时间复杂度为O(1),并且具有非常低的平均常数时间。当命令作用于N个HyperLogLog时,时间复杂度为O(N),常数时间会比单个HyperLogLog要大的多。

使用示例:

  • 53
    点赞
  • 122
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论
HyperLogLog是一种概率性数据结构,主要用于进行基数(distinct count)的近似计数。它可以用来统计集合中元素的数量,而不需要存储每个元素本身。 HyperLogLog原理是通过一定的算法和数据结构,在较小的内存占用下,对大数据集的基数进行近似计数。在实际应用中,HyperLogLog通常与Redis等数据存储系统配合使用HyperLogLog使用语法主要包括pfadd和pfcount两个命令。pfadd用于添加数据到HyperLogLog中,而pfcount用于对HyperLogLog进行基数的统计。虽然算法比较复杂,但是使用起来相对容易掌握。 在HyperLogLog中,使用pfadd命令添加数据时,并不会一次性分配大量内存,而是随着基数的增加逐渐增加内存分配。而pfmerge命令用于将不同的HyperLogLog合并到一个12k大小的key中。这是因为在HyperLogLog的合并操作中,需要单独比较每个桶的值。 HyperLogLog算法最初是为了处理大数据量的统计而被发明的。因此,它非常适合那些对精确度要求不高,但对性能和存储空间要求较高的场景。虽然HyperLogLog提供的计数是近似的,但标准误差只有0.81%。因此,在页面用户访问量较大且对计数的准确度要求不高的情况下,可以使用HyperLogLog进行基数的近似计数,既能节省存储空间,又能保证较好的性能。<span class="em">1</span><span class="em">2</span><span class="em">3</span><span class="em">4</span>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李子捌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值