问题很简单:我需要找到最佳策略来基于 Redis 的表示来实现准确的 HyperLogLog 联合——这包括在导出数据结构以供其他地方使用时处理它们的稀疏/密集表示。
两种策略
有两种策略,其中一种似乎非常简单。我查看了实际的 Redis 源代码,但我遇到了一些麻烦(我自己在 C 语言中并不大),从精度和效率的角度来看,使用他们的内置结构/例程或开发我自己的结构/例程是否更好. 对于它的价值,我愿意牺牲空间和一定程度的错误(stdev +-2%)来追求极大的集合效率。
一、包容原则
到目前为止,两者中最简单的——基本上我只会使用无损联合(PFMERGE)结合这个原则来计算重叠的估计值。测试似乎表明在许多情况下这种运行可靠,尽管我无法准确处理实际效率和准确性(某些情况下会产生 20-40% 的错误,这在这个用例中是不可接受的)。
基本上:
aCardinality + bCardinality - intersectionCardinality
或者,在多组的情况下......
aCardinality + (bCardinality x cCardinality) - intersectionCardinality
似乎在许多情况下都能以良好的准确性工作,但我不知道我是否相信它。虽然 Redis 有许多内置的低基数修饰符旨在规避已知的 HLL 问题,但我不知道在大小差异很大的集合中是否仍然存在疯狂不准确的问题(使用包含/排除)......
2. Jaccard索引交集/MinHash
这种方式似乎更有趣,但我的一部分感觉它可能在计算上与 Redis 的一些现有优化重叠(即,我没有从头开始实现我自己的 HLL 算法)。
使用这种方法,我将使用 MinHash 算法对 bin 进行随机采样(我认为 LSH 实现不值得麻烦)。这将是一个单独的结构,但通过使用 minhash 获取集合的 Jaccard 索引,您可以有效地将联合基数乘以该索引以获得更准确的计数。
问题是,我不太精通 HLL,虽然我很想深入研究 Google 论文,但我需要一个可行的实施方案。有可能我忽略了 Redis 现有优化的一些基本考虑因素,或者在算法本身允许计算成本低的交集估计和相当宽松的置信范围。
因此,我的问题:
如果我愿意牺牲空间(并在较小程度上牺牲准确性),如何使用 redis 最有效地获得 N 个巨大(十亿)集的计算成本低廉的交集估计?