1.HyerLogLog的基本原理
HyerLogLog不是一种数据结构,而是一种基数算法。
1.1 基数
基数指的是在一个集合内,不重复内容的个数。
1.2 Loglog Counting
1.2.1 基本算法
通过阅读解读Cardinality Estimation算法(第三部分:LogLog Counting)我们最后可以得出,在经过Hash函数的计算后,备选集合转换成的集合几乎服从均匀分布。假设集合的基数为n。为集合元素中首个“1”位置最靠后出现的时候,“1”所在的比特串位置。此时可以作为基数n的约估值。
1.2.2 分桶平均
根据LLC的基本算法得到的是一个估值,因此随机误差会使结果产生较大的误差,在实验中我们减少随机误差的常用方法就是多次测量,取平均值。我们采用分桶平均的思想来减少误差,对于每一个元素,以Hash函数后的前k位作为桶号,L作为比特串的长度,其中,m为哈希空间平分的桶数,在分桶平均思想下,每一个L-k的比特位进行基数估算。设为M[i],对m求平均再估值得:
n̂ =
1.2.3 偏差修正
在Loglog Counting of Large Cardinalities论文中讨论了分桶后算法估值的精确性,并通过分析和论证得到了一个常数am来进一步提高估算算法的精确(有兴趣的读者可以查看前文提及的论文详细分析及论证),最后得到估算公式:
n̂ =
1.3 HyperLogLog Counting
LLC算法已经能得到不错的估值,但是由于LLC算法在选取求平均数的方法存在天然的缺陷,对离群值特别敏感,为了弥补这样的缺陷,《HyperLogLog: the analysis of a near-optimal cardinality estimation algorithm》进行分析,并提出更好的实现。
1.3.1 算法优化
在基本算法和分桶方式一致的情况下,HyperLogLog选取了调和平均数代替Loglog的几何平均数(算式推导可以查看博文下的参考链接或者论文),估计公式变更为:
n̂ =
1.3.2 分段偏差修正
HyperLogLog论文中的讨论部分对估值与分桶不同比例下导致的估值偏差提出了修正方案:
当n̂ 时,使用文中没详细提到的LC算法,即n̂=
当n̂时候,n̂ =
当n̂时候,n̂ =
2. 命令
从第一小节我们可以看到HyperLogLog的背后的实现原理是比较复杂的,但是幸好Redis已经为我们实现了,我们只需要几个命令就能使用上HyperLogLog
2.1 添加数据
pfadd testlog "123" "321" "123"
2.2 统计
pfcount testlog
2.3 合并
pfadd testlog2 "567" "321" "123"
pfmerge mergelog testlog2 testlog
pfmerge可以对多个HyerLogLog进行并集
3. HyerLogLog优缺点
优点:
1.可以以极小的容量(比bitmap还小)来统计数据。
缺点:
1.HyperLogLog不是100%正确估算结果,Redis官方给出失误率0.81%。
2.HyperLogLog无法知道某条数据是否在对象中,它只能对插入数据进行统计。
《Loglog Counting of Large Cardinalities》
《HyperLogLog: the analysis of a near-optimal cardinality estimation algorithm》
书籍:《Redis开发与运维》