Mongorestore似乎耗尽了内存并杀死了mongo进程

时间:2018-04-19 18:42:51

标签: mongodb docker rancher mongorestore mongodb-3.6

在当前设置中,有两个Mongo Docker容器,在主机A和B上运行,Mongo版本为3.4,并在副本集中运行。我想将它们升级到3.6并增加一个成员,这样容器就可以在主机A,B和C上运行。容器有8GB内存限制,没有分配交换(当前),并在Rancher中管理。因此,我的计划是启动三个新容器,为这些容器初始化副本集,从3.4容器中获取转储,并将其恢复为新的副本集主服务器。

转储很顺利,它的大小约为16GB。当我尝试将其恢复到新的3.6主服务器时,恢复启动正常,但在它恢复了大约5GB的数据之后,mongo进程似乎被OS / Rancher杀死,而容器本身没有重启,而MongoDB进程只是崩溃并重新加载自己。如果我再次将mongorestore运行到同一个数据库,它会为所有已插入的条目显示唯一键错误,然后从停止的位置继续,仅在5GB左右后再次执行相同操作。所以似乎mongorestore将它恢复的所有条目加载到内存中。

所以我必须得到一些解决方案,并且:

  1. 每次崩溃时,只需运行mongorestore命令,使其继续停止。它可能应该有效,但我觉得有点不安。
  2. 一次恢复数据库一个集合,但最大的集合大于5GB,因此它也无法正常工作。
  3. 将交换或物理内存(临时)添加到容器中,以便在进程耗尽物理内存后进程不会被终止。
  4. 其他什么,希望是更好的解决方案?

6 个答案:

答案 0 :(得分:2)

由于mongorestore继续成功停止,听起来你的磁盘空间不足,因此关注内存问题是正确的反应。在mongorestore进程中,你肯定会耗尽内存。

我强烈建议使用交换空间,因为这是最简单,最可靠,最少hacky,可以说是最正式支持的处理此问题的方法。

或者,如果您出于某种原因完全反对使用交换空间,则可以暂时使用内存量较大的节点,在此节点上执行mongorestore,允许其复制,然后关闭节点将其替换为分配给它的资源较少的节点。这个选项应该可行,但是对于更大的数据集可能会变得相当困难,并且对于这样的事情来说是相当过分的。

答案 1 :(得分:2)

在这里记录一下我在 2020 年使用 mongodb 4.4 的经验:

我在具有 4GB 内存的机器上恢复 5GB 集合时遇到了这个问题。我添加了似乎有效的 4GB 交换,但我不再看到 KILLED 消息。

然而,过了一会儿我发现我丢失了很多数据!事实证明,如果 mongorestore 在最后一步(100%)内存不足,它不会显示已终止,但它尚未导入您的数据

您想确保看到最后一行:

[########################]  cranlike.files.chunks  5.00GB/5.00GB  (100.0%)
[########################]  cranlike.files.chunks  5.00GB/5.00GB  (100.0%)
[########################]  cranlike.files.chunks  5.00GB/5.00GB  (100.0%)
[########################]  cranlike.files.chunks  5.00GB/5.00GB  (100.0%)
[########################]  cranlike.files.chunks  5.00GB/5.00GB  (100.0%)
restoring indexes for collection cranlike.files.chunks from metadata
finished restoring cranlike.files.chunks (23674 documents, 0 failures)
34632 document(s) restored successfully. 0 document(s) failed to restore.

就我而言,我需要 4GB 内存 + 8GB 交换,以导入 5GB GridFS 集合。

答案 2 :(得分:1)

Rather than starting up a new replica set, it's possible to do the entire expansion and upgrade without even going offline.

  1. Start MongoDB 3.6 on host C
  2. On the primary (currently A or B), add node C into the replica set
  3. Node C will do an initial sync of the data; this may take some time
  4. Once that is finished, take down node B; your replica set has two working nodes still (A and C) so will continue uninterrupted
  5. Replace v3.4 on node B with v3.6 and start back up again
  6. When node B is ready, take down node A
  7. Replace v3.4 on node A with v3.6 and start back up again

You'll be left with the same replica set running as before, but now with three nodes all running v.3.4.

PS Be sure to check out the documentation on Upgrade a Replica Set to 3.6 before you start.

答案 3 :(得分:1)

增加交换大小,因为另一个答案对我来说是可行的。同样,<article> <div class="label">Short label</div> <div class="value">Short string</div> <div class="label">A very long label</div> <div class="value">A very long string, so long in fact that it will have to wrap more then one line, possibly even more if you have a sufficiently small screen</div> </article>选项控制应并行转储/还原的集合--numParallelCollections / mongodump的数量。默认值为4,这可能会占用大量内存。

答案 4 :(得分:1)

作为测试副本集的一部分,我遇到了类似的问题,该问题在一台计算机上运行3个节点(总共8GB RAM)。 default storage cache size为0.5 *(总RAM-1GB)。 mongorestore导致每个节点在还原时使用完整的缓存大小并消耗所有可用的RAM。

我正在使用ansible为mongod.conf的这部分模板化,但是您可以将cacheSizeGB设置为任何合理的数量,以便多个实例不占用RAM。

storage:
    wiredTiger:
        engineConfig:
            cacheSizeGB: {{ ansible_memtotal_mb /  1024 * 0.2 }}

答案 5 :(得分:1)

我通过使用mongod的--wiredTigerCacheSizeGB参数解决了OOM问题。摘自下面的docker-compose.yaml

version: '3.6'
services:
    db:
        container_name: db
        image: mongo:3.2
        volumes:
            - ./vol/db/:/data/db
        restart: always
        # use 1.5GB for cache instead of the default (Total RAM - 1GB)/2:
        command: mongod --wiredTigerCacheSizeGB 1.5