Mongorestore 似乎 运行 内存不足并终止了 mongo 进程

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

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

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

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

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

由于 mongorestore 在成功停止的地方继续运行,因此听起来您没有 运行 磁盘 space,关注内存问题是正确的响应。在 mongorestore 进程中,您肯定 运行 内存不足。

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

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

无需启动新的副本集,甚至无需离线即可完成整个扩展和升级。

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

您将得到与以前相同的副本集 运行,但现在三个节点都是 运行 v.3.4.

PS 请务必在开始前查看 Upgrade a Replica Set to 3.6 上的文档。

正如另一个答案指出的那样,增加交换大小对我来说很有效。此外,--numParallelCollections 选项控制集合的数量 mongodump/mongorestore 应该 dump/restore 并行。默认为4,可能会占用大量内存。

我 运行 遇到了类似的问题 运行 一台机器上的 3 个节点(总共 8GB RAM)作为测试副本集的一部分。 default storage cache size 是 .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

只是在这里记录我在 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 集合。

我的场景类似于@qwertz,但为了能够将所有集合上传到我的数据库,创建了以下脚本来处理部分上传;上传每个集合 one-by-one 而不是尝试一次发送所有数据库是正确填充它的唯一方法。

populate.sh:

#!/bin/bash

backupFiles=`ls ./backup/${DB_NAME}/*.bson.gz`
for file in $backupFiles
do
  file="${file:1}"
  collection=(${file//./ })
  collection=(${collection//// })
  collection=${collection[2]}

  mongorestore \
  $file \
  --gzip \
  --db=$DB_NAME \
  --collection=$collection \
  --drop \
  --uri="${DB_URI}://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/"
done

Dockerfile.mongorestore:

FROM alpine:3.12.4

RUN [ "apk", "add", "--no-cache", "bash", "mongodb-tools" ]

COPY populate.sh .

ENTRYPOINT [ "./populate.sh" ]

docker-compose.yml:

...

  mongorestore:
    build:
      context: .
      dockerfile: Dockerfile.mongorestore
    restart: on-failure
    environment:
      - DB_URI=${DB_URI}
      - DB_NAME=${DB_NAME}
      - DB_USERNAME=${DB_USERNAME}
      - DB_PASSWORD=${DB_PASSWORD}
      - DB_HOST=${DB_HOST}
      - DB_PORT=${DB_PORT}
    volumes:
      - ${PWD}/backup:/backup

...