Mongo DB读取400万份文件

时间:2016-11-16 04:36:43

标签: mongodb mongodb-query

我们有每天运行的计划作业,此作业查找当天匹配的文档并获取文档并执行最小转换并将其发送到队列以进行下游处理。通常,我们每天要处理4百万份文档。我们的目标是在一小时内完成加工。我正在寻找有关从MongoDB快速阅读400万份文档的最佳实践的建议吗?

1 个答案:

答案 0 :(得分:1)

MongoDB Async driver是低开销查询的第一站。在该页面上使用SingleResultCallback的{​​{3}}非常好:

Block<Document> printDocumentBlock = new Block<Document>() {
    @Override
    public void apply(final Document document) {
        System.out.println(document.toJson());
    }
};
SingleResultCallback<Void> callbackWhenFinished = new SingleResultCallback<Void>() {
    @Override
    public void onResult(final Void result, final Throwable t) {
        System.out.println("Operation Finished!");
    }
};

collection.find().forEach(printDocumentBlock, callbackWhenFinished);

异步数据库驱动程序中的一种常见模式是允许结果在可用时立即传递以进行处理。使用OS级别的异步I / O将有助于降低CPU开销。这引出了下一个问题 - 如何获取数据。

如果没有看到你工作的具体细节,你可能希望将结果放入内存队列中,以便此时由另一个线程获取,这样读者线程就可以继续读取结果。 example可能是合适的。 ArrayBlockingQueueadd更合适,因为如果工作人员无法跟上(保持平衡),它将阻止读者线程。理想情况下,您不希望它备份,这是需要多个线程的地方。如果结果的顺序很重要,请使用单个工作线程,否则使用put将队列传递给构造函数。如果结果在读取时以某种方式被丢弃(即如果你是立即发送另一个查询以删除它们),那么使用内存中队列确实会导致数据丢失的可能性,并且读取器进程崩溃。

此时,要么进行最小变换&#39;在工作线程上,或在工作者中序列化它们并将它们放在真正的队列上(例如RabbitMQ,ZeroMQ)。将它们放到一个真实的队列中可以将工作分成多个机器,并提供可选的持久性,允许恢复工作,这些队列具有很好的可扩展性集群选项。然后,这些机器可以将结果放入您在问题中提到的队列中(假设它具有容量)。

这样的系统中的瓶颈是一台机器可以通过单个mongo查询获得多快的速度,以及最终队列可以处理多少结果。所有其他部分(MongoDB,队列,工作机器的#)都是可单独扩展的。通过在查询机器上尽可能少地完成工作并将该工作推送到其他机器上,可以大大减少影响。听起来您的目的地队列无法控制。

当试图解决瓶颈问题时,测量至关重要。预先在您的应用程序中添加ThreadPoolExecutor可以让您知道在事情进展顺利时哪些方面需要改进。

该设置可以构建一个相当可扩展的系统。我之前已经建立了许多类似的系统。除此之外,您还需要调查将数据转换为metrics之类的内容。