mongodb - 寻找 1 x 100 万个交叉点的最佳解决方案? Redis、Mongo、其他

大家好,提前致谢。 我是 NoSQL 游戏的新手,但我目前的工作地点要求我对一些大数据进行设置比较。

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

预计算不是一种选择,因为我们正在为 10 亿用户的潜在客户群进行拍摄。

(这些标签是分层的,所以有一个标签意味着你也有它的父标签和祖先标签。暂时把这些信息放在一边。)

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

我一直在探索我的选择,Redis 中的设置交集似乎是理想的。然而,我在互联网上的拖钓并没有透露需要多少内存才能容纳一百万个标签集。我意识到交叉口会快如闪电,但这是 Redis 的可行解决方案吗?

我意识到这是蛮力和低效的。我还想用这个问题来获得有关过去处理此类问题的方法的建议。如前所述,标签存储在树中。我也开始将 Mongodb 视为一种可能的解决方案。

再次感谢

最佳答案

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

Redis 可以使用优化的“intset”格式存储整数集。见 http://redis.io/topics/memory-optimization了解更多信息。

我相信这里正确的数据结构是目标标签集的集合,加上将标签映射到目标标签集的反向索引。

存储两个目标标签集:

 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 个标签),当目标标签集共享的标签非常少时,内存消耗接近 4 GB(反向索引中超过 32M 的条目),并且当标签被大量共享时大约 500 MB(反向索引中只有 100K 条目)。

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

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 万个目标标签集测试客户标签集。您可以依靠反向索引将搜索范围限制在可接受的范围内。

https://stackoverflow.com/questions/11095331/

相关文章:

mongodb - 使用 mongodb 或 cassandra 的空间数据

java - 如何直接从 Java 中的 mongodb 查询返回原始 JSON?

mongodb - MongoDB中聚合($match)和查找之间的区别?

javascript - 如何重定向到另一个网页?

node.js - 模拟/测试 Mongodb 数据库 Node.js

mongodb - 使用 sphinx 搜索与 mongodb 作为数据源

javascript - MongoError,错误 :E11000 duplicate key e

javascript - 如何检查元素是否隐藏在 jQuery 中?

java - 编码对象时未使用 MongoDB BSON 编解码器

javascript - 如何检查字符串是否包含 JavaScript 中的子字符串?