4

我们需要释放一些 MongoDB 空间,并且我们确定了可以从集合中安全删除的 100Gb 以上的文档。

因此,我们将它们从具有以下设置的测试环境中删除:

  • MongoDB 3.0.1 版
  • 没有分片
  • 1 个节点,无副本
  • 有线老虎引擎

完成后,我们发现磁盘上的空间仍在使用,需要回收。我们找到了这篇文章,它帮助了我们:在运行两者之后

db.runCommand({repairDatabase: 1})

db.runCommand({compact: collection-name })

我们释放了 100Gb +。

然后我们继续生产,忘记了设置是不同的,因为我们有 1 个副本节点:

  • MongoDB 3.0.1 版
  • 没有分片
  • 1个主节点,1个副本节点
  • 有线老虎引擎

删除文件后,我们运行

db.runCommand({repairDatabase: 1})

并收到OK消息(过了一会儿,10 分钟 +)。我们试着跑步

db.runCommand({compact: collection-name })

并得到这个错误:

不会在活动副本集主节点上运行紧凑,因为这是一个缓慢的阻塞操作。使用 force:true 强制

所以我们跑

db.runCommand({compact: collection-name, force: true })

并收到OK消息(几乎立即),但空间磁盘仍在使用,它没有被释放。

我们搜索了使用副本集运行repairDatabaseandcompact命令的解决方案,但建议的重点是避免停机,好像这是唯一的问题。但是,我们可以安排停机时间,而我们的问题是命令不能按预期工作,因为空间实际上并没有被回收

我们做错了什么?

4

1 回答 1

4

对于副本集配置,恢复空间的最佳和最安全的方法是执行初始同步。如果您需要从集合中的所有节点恢复空间,您可以执行滚动初始同步。也就是说,在每个辅助节点上执行初始同步,然后最终降级主节点并对其执行初始同步。

请注意,只有当您的部署包含至少三个节点副本集时,滚动初始同步才可能(原因我将在下面描述)。

滚动初始同步方法是执行副本集维护的最安全方法,而且它还没有停机作为奖励。

话虽如此,有几点值得一提:

关于compact

MongoDB 3.0.x 上 WiredTiger 上的compact命令受此错误影响:SERVER-21833,已在 MongoDB 3.2.3 中修复。在此版本之前,compactWiredTiger 可能会静默失败。

关于repairDatabase

请不要repairDatabase在副本集节点上运行。强烈不建议这样做,如repairDatabase 页面中所述。这个名字repairDatabase有点误导,因为该命令不会尝试修复任何东西。该命令旨在在磁盘损坏时使用,这可能导致文档损坏。

repairDatabase命令可以更准确地描述为“打捞数据库”。也就是说,它通过丢弃损坏的文档来重新创建数据库,以尝试使数据库进入可以启动它并从中挽救完整文档的状态。

在副本集中,MongoDB 期望集合中的所有节点都包含相同的数据。如果您repairDatabase在副本集节点上运行,则该节点有可能包含未检测到的损坏,并且repairDatabase会尽职尽责地删除损坏的文档。可以预见的是,这使得该节点包含与集合的其余部分不同的数据集。如果更新碰巧命中了该单个文档,则整个集合可能会崩溃。更糟糕的是,这种情况完全有可能长期处于休眠状态,只是突然袭击,没有明显的原因。

关于您的设置:

我注意到在您的生产环境中,您创建了一个包含两个节点的副本集。不建议使用此设置,因为单个节点的故障将使剩余节点成为辅助节点,因此不允许写入集合。

由于 MongoDB 高可用性的工作方式(请参阅Replica Set Election),强烈建议至少部署三个数据承载节点,或者至少添加一个仲裁节点(请参阅Replica Set Members),以便您的副本集包含一个奇数成员数量。

在副本集中只有两个成员也会使滚动升级/初始同步/维护变得更加困难,在某些情况下甚至是不可能的。

MongoDB 3.0.1 于 2015 年3 月 17 日发布,距撰写本文时已超过 2 年。如果您被迫使用 MongoDB 3.0 系列,请考虑迁移到 3.0.15。或者更好的是,到 3.4.7(截至 2017 年 8 月 10 日的最新版本),其中包含对 3.0.1 的巨大改进。

于 2017-08-10T01:35:28.080 回答