HyperLogLog in Redis


HyperLogLog 主要用于大量数据的一些统计以及合并工作.
本文主要简单的介绍一下HyperLogLog概念,以及在Redis当中的实现.

让我们从一个故事讲起

抛硬币

现在我们抛硬币,每组8次,将每次为正面的硬币记为正,否则记为反.
那么我可以得到,随机的记录如下:

正正反正反正反正反正
正反反正反正反正反正
...

就这样一致抛下去,最终我们会有很多不同的结果的组.
现在就从概率学的角度看待这个问题,我们的得到正正正正正正正X要比得到正正正正XXXX难的多.
难的多,只是一个口语话的描述,说明我们就需要更多的实验组去获得这样一组数据.
这样我们就可以拿从起始位置算起连续的个数去估计当前的数据的数量.

现在我们将每组开头连续的正记录次数,第一组为2,第二组为1.
那么我们可以预估当前的不同的元素个数为2^2

当我们的试验次数足够多的时候我们可以得出一组都为正,那么此时的试验不同的元素就变为了2^8.

由此可以得出的结论是当足够随机而且实验次数足够多的时候,我们就可以用这样的方法来估计不同元素数量.
当然这样是有误差的,一般情况下误差控制在1%以下,非精准要求的业务可以采用这个算法,可以极大的提升空间存储的效率.
HyperLogLog 采取了更好的策略得到更好的结果.

HyperLogLog Algorithm

The basis of the HyperLogLog algorithm is the observation that the cardinality of a multiset of uniformly distributed random numbers can be estimated by calculating the maximum number of leading zeros in the binary representation of each number in the set. If the maximum number of leading zeros observed is n, an estimate for the number of distinct elements in the set is 2n. -From wiki

HyperLogLog算法是在一组二进制数的集合中观察一致连续随机数字的基数,基数是使用最大前导0的个数进行估算集合中的元素的个数.如果最大前导0是n(位置从1开始计算)位置,那么估算在集合当中唯一的元素个数就是2^n个.

The simple estimate of cardinality obtained using the algorithm above has the disadvantage of a large variance. In the HyperLogLog algorithm, the variance is minimised by splitting the multiset into numerous subsets, calculating the maximum number of leading zeros in the numbers in each of these subsets, and using a harmonic mean to combine these estimates for each subset into an estimate of the cardinality of the whole set.

这样简单的估算有个缺点就是方差很大.在HyperLogLog当中,方差可以通过将集合分割多个子集被最小化,分别计算在每个子集当中最大前导0的个数.根据每个子集的估算的值得到调和平均数去估算整个集合的基数.

分子集:

以8位举例

00|100000
10|001000
01|001000
11|010000

前两位作为子集的标志,后边6位计算最大位数前导0,这里的前导0是去掉子集的标志位的最大位数.

Redis的实现

首先值可以被hash为64位二进制数,集合当中可以放入字符串,被hash成64位数,Redis使用的前14位作为子集的标志,用来定位内存当中的偏移值(offset).
那么我们就有2^14(16384)个子集(Bucket).误差为0.81%
剩下的50位计算最大前导0的位数,Redis每个Bucket只用6位存储最大前导0的个数,最大是50.

因此得到 16384 * 6 / 8 = 12288个字节.
因此数据内容格式如下:

 110010  110011 000000  -->numbers of leading zero
   	0			  1				2    --> subset tag,offset = 6 * subset tag 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值