1

关于我之前的问题(如何快速构建大规模分析服务器? )我现在将我的分析数据提供给 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 的所有事件。次要聚合将使用元数据对事物进行分组(使用客户端 1 与客户端 2 的百分比等)。所有聚合都将由系统定义,因此至少此时用户无法自行设置它们。因此,据我了解,分片应该通过 ID 完成,因为大多数聚合将以 ID 为中心?此外,这应该意味着任何给定 ID 上的最新事件始终在内存中,因为 Mongo 将最新内容保存在内存中,并且只会将溢出转储到磁盘。

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

编辑:添加示例数据

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

4

3 回答 3

2

尽可能快地获得 mapreduce 的步骤:

  • 优化您的数据,以便您拥有尽可能多的内存。去磁盘“杀死”(让它真的很慢)一切!(请参阅下面关于我为什么不建议使用 mapreduce 的评论!)

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

  • 如果您聚合的维度数量是已知且有限的,那么为什么不在插入时存储和增加聚合呢?而不是查询它?(显然这会在插入时增加更多的负载/处理)MongoDB 文档关于预聚合模式

在针对每天获得数百万次插入的数据集运行时,我可以采取哪些特定于 Mongo 的技巧来使事情变得更快?

  • 分片可扩展您的写入。如果加载了单个节点,则添加另一个。选择一个合适的分片键来实现平衡写入(一个分片不会得到所有的写入)

其他需要考虑的事项:

MapReduce 速度慢,不适合在线操作。它是一个批处理框架。它也是单线程的,就像 JS 引擎一样。它在与 JS 之间进行转换也有开销。我使用聚合框架来绕过这些限制,并发现它比使用 mongodb mapreduce 命令更快且更具可扩展性。

如果执行 mapreduce 或聚合框架操作,请尝试在内存中获取尽可能多的活动数据集!去磁盘会杀死两者的性能。我发现关于右平衡索引的 mongodb 注释对于将我们的工作集保存在内存中非常宝贵。

于 2012-10-30T06:23:47.740 回答
1

MapReduce 不会很快。它使用 JavaScript 引擎做一件事,因此您需要运行的代码越多来查询数据就越慢。您可以越多地利用具有索引的本机数据库引擎越好。你能提供一些你的数据结构可能是什么样子的例子吗?

于 2012-10-29T10:26:13.377 回答
1

用我自己的风格扩展另一个答案;map reduce 是许多处理的可靠选择。毫无疑问,如果您完全做到这一点,map reduce 将成为您分析的重要核心。

最好的 MR 类型是增量式的,它构建某些事件和人员的档案统计信息,以缩小整体数据库大小和提取所有旧数据的工作集大小。

至于实时使用,我发现(从 Google 用户组中 MongoDB 早期关于该主题的许多讨论中)最好的方法是预先聚合您的数据,以便一个简单的线性查询,如:db.some_preaggregated_data.find({date: {$gt, $lt}})将得到您的结果。这简化了数据的分片和范围,更不用说你的工作集大小了。总体而言,提供了更高性能的操作。

我会推荐一件事:- 如果您真的希望它能够实时完全扩展,请不要进入聚合框架或复杂查询。它将开始在如此庞大的数据集上创建过多的工作。您将需要完整的锁、工作集等,使用简单的find()查询来满足您对大表格式的需求。

于 2012-10-30T15:28:21.940 回答