Mongorestore 似乎内存不足并杀死了 mongo 进程
Posted
技术标签:
【中文标题】Mongorestore 似乎内存不足并杀死了 mongo 进程【英文标题】:Mongorestore seems to run out of memory and kills the mongo process 【发布时间】:2018-09-30 08:55:28 【问题描述】:在当前设置中,有两个 Mongo Docker 容器,在主机 A 和 B 上运行,Mongo 版本为 3.4,并在副本集中运行。我想将它们升级到 3.6 并增加一个成员,以便容器可以在主机 A、B 和 C 上运行。容器有 8GB 内存限制并且没有分配交换空间(当前),并在Rancher 中进行管理。所以我的计划是启动三个新容器,为它们初始化一个副本集,从 3.4 容器中获取一个转储,然后将其恢复为新的副本集 master。
转储文件很顺利,其大小约为 16GB。当我尝试将其恢复到新的 3.6 主服务器时,恢复开始正常,但在恢复了大约 5GB 的数据后,mongo 进程似乎被 OS/Rancher 杀死,而容器本身没有重新启动,MongoDB 进程只是崩溃并重新加载自己再次备份。如果我再次将 mongorestore 运行到同一个数据库,它会为所有已插入的条目显示唯一键错误,然后从中断处继续,仅在 5GB 左右后再次执行相同操作。所以看起来 mongorestore 会将它恢复的所有条目加载到内存中。
所以我得想办法解决这个问题,并且:
-
每次它崩溃时,只需运行 mongorestore 命令,它就会从中断的地方继续。它应该可以工作,但我觉得这样做有点不安。
一次恢复数据库一个集合,但最大的集合大于 5GB,因此也无法正常工作。
向容器添加交换或物理内存(临时),这样进程就不会在物理内存用完后被终止。
还有其他问题,希望有更好的解决方案?
【问题讨论】:
这意味着您在单个主机上运行 3 个需要内存的进程:mongod v3.4、新的 mongod v3.6 和 mongorestore? 既然你这么说......是的。 【参考方案1】:在这里记录一下我在 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 集合。
【讨论】:
感谢您的记录。应该有“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
【讨论】:
【参考方案3】:作为测试副本集的一部分,我遇到了在单台机器上运行 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
【讨论】:
【参考方案4】:正如另一个答案指出的那样,增加交换大小对我有用。此外,--numParallelCollections
选项控制集合的数量mongodump
/mongorestore
应该并行转储/恢复。默认为 4,可能会消耗大量内存。
【讨论】:
将--numParallelCollections
设置为 1
是我的案例中最有效和最简单的解决方案:具有 1GB RAM 的 EC2 实例。【参考方案5】:
无需启动新的副本集,甚至可以在不离线的情况下进行整个扩展和升级。
-
在主机 C 上启动 MongoDB 3.6
在主节点(当前为 A 或 B)上,将节点 C 添加到副本集中
节点 C 将进行数据的初始同步;这可能需要一些时间
完成后,取下节点 B;您的副本集仍然有两个工作节点(A 和 C),因此将继续不间断
将节点 B 上的 v3.4 替换为 v3.6 并重新启动备份
当节点B准备好时,取下节点A
将节点 A 上的 v3.4 替换为 v3.6 并重新启动备份
您将继续运行与以前相同的副本集,但现在三个节点都运行 v.3.4。
PS 在开始之前,请务必查看Upgrade a Replica Set to 3.6 上的文档。
【讨论】:
【参考方案6】:由于 mongorestore 继续成功中断的地方,听起来您并没有用完磁盘空间,因此关注内存问题是正确的响应。您肯定在 mongorestore 过程中内存不足。
我强烈建议使用交换空间,因为这是处理此问题的最简单、最可靠、最不麻烦的方法,并且可以说是最受官方支持的方法。
或者,如果您出于某种原因完全反对使用交换空间,您可以暂时使用具有较大内存量的节点,在该节点上执行 mongorestore,允许其复制,然后关闭该节点并用分配给它的资源较少的节点替换它。这个选项应该可以工作,但对于更大的数据集可能会变得相当困难,并且对于这样的事情来说太过分了。
【讨论】:
通过临时增加内存和添加交换空间来做到这一点,结果很好。还按照 Mongo 文档中的建议永久添加了一些交换。谢谢! 对我来说,使用 -vvv 详细选项运行 mongorestore 至少可以显示“已杀死”,而不是静默失败。添加交换空间并增加 WiredTiger 缓存以匹配对我有用。以上是关于Mongorestore 似乎内存不足并杀死了 mongo 进程的主要内容,如果未能解决你的问题,请参考以下文章