繁体   English   中英

Mongorestore 似乎内存不足并杀死了 mongo 进程

[英]Mongorestore seems to run out of memory and kills the mongo process

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

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

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

  1. 每次崩溃时,只需运行 mongorestore 命令,以便它从停止的地方继续。 它可能应该有效,但我觉得这样做有点不安。
  2. 一次还原一个集合,但最大的集合大于5GB,因此它也无法正常工作。
  3. 将交换或物理内存(临时)添加到容器中,以便在进程用完物理内存后该进程不会被终止。
  4. 别的东西,希望有更好的解决方案?

正如另一个答案指出的那样,增加交换大小对我有用。 此外, --numParallelCollections选项控制mongodump / mongorestore应该并行转储/恢复的集合数量。 默认值为 4,可能会消耗大量内存。

由于 mongorestore 在成功停止的地方继续运行,听起来您并没有耗尽磁盘空间,因此专注于内存问题是正确的响应。 在 mongorestore 过程中,您肯定会耗尽内存。

我强烈建议使用交换空间,因为这是最简单、最可靠、最简单的方法,并且可以说是处理此问题的最受官方支持的方法。

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

仅在此处记录我在 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 集合。

无需启动新的副本集,甚至可以在不下线的情况下进行整个扩展和升级。

  1. 在主机 C 上启动 MongoDB 3.6
  2. 在主节点(当前为 A 或 B)上,将节点 C 添加到副本集中
  3. 节点 C 将进行数据的初始同步; 这可能需要一些时间
  4. 完成后,取下节点B; 您的副本集仍然有两个工作节点(A 和 C),因此将继续不间断
  5. 将节点 B 上的 v3.4 替换为 v3.6 并重新启动
  6. 当节点 B 准备好时,取下节点 A
  7. 将节点 A 上的 v3.4 替换为 v3.6 并重新启动

您将保留与以前一样运行的副本集,但现在三个节点都运行 v.3.4。

PS 在开始之前,请务必查看有关将副本集升级到 3.6的文档。

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

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

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

我通过使用 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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM