寻找1x100万集合交叉点的最佳解决方案?雷迪斯、蒙戈、其他

kpbwa7wx  于 2022-10-08  发布在  其他
关注(0)|答案(3)|浏览(167)

大家好,提前谢谢大家。我是NoSQL游戏的新手,但我目前的工作地点让我负责对一些大数据进行集合比较。

我们的系统有客户标签集和目标标签集。标签是一个8位数字。
客户标记集最多可以有300个标记,但平均为100个标记
目标标签集可以具有多达300个标签,但平均为40个标签。

预先计算不是一种选择,因为我们正在争取10亿潜在用户群。

(这些标记是分层的,因此只有一个标记意味着您也有它的父标记和祖先标记。暂时把这些信息放在一边。)

当客户访问我们的网站时,我们需要尽快将他们的标签集与100万个目标标签集相交。客户集必须包含要匹配的目标集的所有元素。

我一直在探索我的选择,雷迪斯的SET交叉口似乎是理想的选择。然而,我在互联网上的搜索并没有透露需要多少内存才能容纳100万个标签集。我知道交叉路口会很快,但这是雷迪斯可行的解决方案吗?

我意识到这是一种蛮力和低效。我也想用这个问题作为一种手段,就过去如何处理这类问题提出建议。如前所述,标签存储在树中。我也开始考虑将MongoDB作为一种可能的解决方案。

再次感谢

hfsqlsce

hfsqlsce1#

这是一个有趣的问题,我认为Redis可以在这方面提供帮助。

Redis可以使用优化的“intset”格式存储整数集。有关详细信息,请参阅http://redis.io/topics/memory-optimization

我相信这里正确的数据结构是目标标记集的集合,外加一个反向索引来将标记Map到它们的目标标记集。

要存储两个目标标记集,请执行以下操作:

0 -> [ 1 2 3 4 5 6 7 8 ]
 1 -> [ 6 7 8 9 10 ]

我会使用:


# Targeted tag sets

 sadd tgt:0 1 2 3 4 5 6 7 8
 sadd tgt:1 2 6 7 8 9 10
 # Reverse index
 sadd tag:0 0
 sadd tag:1 0
 sadd tag:2 0 1
 sadd tag:3 0
 sadd tag:4 0
 sadd tag:5 0
 sadd tag:6 0 1
 sadd tag:7 0 1
 sadd tag:8 0 1
 sadd tag:9 1
 sadd tag:10 1

当从系统添加/移除目标标签集时,该反向索引非常容易维护。

全局存储器消耗取决于多个目标标签集所共有的标签的数量。在Redis中存储伪数据和模拟内存消耗是相当容易的。我已经使用simple node.js script完成了。

对于100万个目标标签集(标签为8位数字,每组40个标签),当目标标签集共享的标签很少时(倒排索引中超过3200万条),内存消耗接近4 GB,当标签被大量共享时(倒排索引中只有10万条),内存消耗约为500MB

使用这种数据结构,找到包含给定客户的所有标签的目标标签集非常高效。

1- Get customer tag set (suppose it is 1 2 3 4)
2- SINTER tag:1 tag:2 tag:3 tag:4
   => result is a list of targeted tag sets having all the tags of the customer

交集操作是高效的,因为Redis足够智能,可以按基数对集合进行排序,并从基数最低的集合开始。

现在我知道您需要实现相反的操作(即查找目标标记集,其所有标记都在客户标记集中)。反向指数仍能有所帮助。

下面是一个用难看的伪代码编写的示例:

1- Get customer tag set (suppose it is 1 2 3 4)
2- SUNIONSTORE tmp tag:1 tag:2 tag:3 tag:4
   => result is a list of targeted tag sets having at least one tag in common with the customer
3- For t in tmp (iterating on the selected targeted tag sets)
      n = SCARD tgt:t (cardinality of the targeted tag sets)
      intersect = SINTER customer tgt:t
      if n == len(intersect), this targeted tag set matches

因此,您永远不需要针对100万个目标标记集测试客户标记集。您可以依靠反向索引将搜索范围限制在可接受的级别。

xam8gpfp

xam8gpfp2#

这可能会有所帮助:

案例研究:在非常大的集合(120m+和120m+)上使用Redis交集

http://redis4you.com/articles.php?id=016&name=Case+Study%3A+Using+Redis+intersect+on+very+large+sets

t1qtbnec

t1qtbnec3#

所提供的答案最初对我有帮助。然而,随着我们客户群的增长,我偶然发现了一项伟大的技术,涉及到使用Redis字符串位和位操作符非常快速地对数亿用户执行分析。

请看这篇文章。Redis的创建者安提雷兹也经常提到这一点。

http://blog.getspool.com/2011/11/29/fast-easy-realtime-metrics-using-redis-bitmaps/

相关问题