如何将基于MongoDB的分析扩展到每天数百万个事件?

时间:2012-10-29 09:29:30

标签: node.js mongodb analytics

关于我之前的问题(How to quickly build large scale analytics server? )我现在将我的分析数据提供给MongoDB - 每个事件(带有大量元数据)都在视图集中获取自己的文档。

然而,现在我已经遇到了下一个障碍:现在已完成插入并且分析数据正在流动,那么针对该数据运行阻力最小的路径是什么?这个想法是,一旦该数据被分片,特定的视图将运行mapReduces(比如说一个月前具有特定ID的所有事件)。

所以,我的问题是:由于我对MongoDB很新,我需要采取哪些步骤才能尽快获得mapReduces?我应该以不同方式构建原始数据还是每个事件的一个文档是否正确?在针对每天获得数百万次插入的数据集运行时,是否有Mongo特定技巧可以使事情更快地流动?

我更希望保持我的技术堆栈尽可能简单(Node.js + MongoDB),所以我更愿意在没有引入额外技术的情况下完成任务(比如说Hadoop)。

活动的示例文件:

{
    id: 'abc',
    ip: '1.1.1.1',
    type: 'event1',
    timestamp: 1234,
    metadata: {
        client: 'client1'
    }
}

所有主要聚合都将以ID为中心,分析所述ID中的事件,最常用的是获取上个月具有所述ID的所有事件。次要聚合将使用元数据对事物进行分组(使用client1与client2等的百分比)。所有聚合都将由系统定义,因此用户至少不能自己设置它们。因此,据我所知,分片应该通过ID完成,因为大多数聚合将以ID为中心?此外,这应该意味着任何给定ID上的最新事件始终在内存中,因为Mongo将最新内容保存在内存中,并且只将溢出转储到磁盘。

此外,实时不是必需的。虽然,它会很好。 :P

编辑:添加了示例数据

编辑:标题应该是“...每天”而不是“...每页”+更多关于聚合集的规范

3 个答案:

答案 0 :(得分:2)

  

尽快获得mapreduce的步骤:

  • 优化您的数据,以便尽可能地在内存中。进入磁盘'杀戮'(让它真的很慢)一切! (请参阅下面的评论,为什么我建议不要使用mapreduce!)
  

我应该以不同方式构建原始数据吗?

  

在针对每天获得数百万次插入的数据集运行时,是否有Mongo特定的技巧可以让事情更快地流动?

  • 分页缩放您的写入。如果加载了单个节点,则添加另一个节点。选择一个适当的分片键来启用平衡写入(一个分片不会获得所有写入)

需要考虑的其他事项:

MapReduce速度慢,不适合在线操作。它是一个批处理框架。它也是单线程的,就像JS引擎一样。它也有翻译到JS的开销。我使用聚合框架来解决这些限制,并发现它比使用mongodb mapreduce命令更快,更具可伸缩性。

如果执行mapreduce或聚合框架操作,请尝试在内存中获取尽可能多的活动数据集!转到磁盘可以杀死任何一个的性能。我发现在right-balanced index上的mongodb音符对于将我们的工作集保存在内存中是非常宝贵的。

答案 1 :(得分:1)

MapReduce不会很快。它只使用JavaScript引擎,因此运行查询数据所需的代码越多,运行速度就越慢。您可以越多地利用带有索引的本机数据库引擎。 您能举例说明您的数据结构可能是什么样的吗?

答案 2 :(得分:1)

用我自己的味道扩展另一个答案; map reduce是很多处理的坚实选择。毫无疑问,如果你完全做到这一点,map reduce将成为你分析的重要核心。

最好的MR是一种增量式的MR,它可以构建某些事件和人员的档案统计数据,从而缩小整个数据库大小和工作集大小,从而提取所有旧的,尘土飞扬的数据。

至于实时使用情况,我发现(在Google用户群中MongoDB早期的许多关于此主题的讨论)最好的方法是预先汇总您的数据,以便进行简单的线性查询,例如:{{1会得到你的结果。这样可以简化数据的分片以及数据的范围,更不用说您的工作集大小了。整体而言,提供更高效的操作。

我建议一件事: - 如果你真的希望这个实时扩展,那么不要进入聚合框架或复杂查询。它将开始在如此庞大的数据集上创建太多的工作。您需要使用简单的db.some_preaggregated_data.find({date: {$gt, $lt}})查询来完整锁定,工作集等,以满足您在大表格格式中的需求。