gpt4 book ai didi

mongodb - 为什么我的 MongoDB 副本总是落后?

转载 作者:行者123 更新时间:2023-12-02 00:51:56 25 4
gpt4 key购买 nike

昨晚将一个集合转换为一个上限集合时,我的次要的 optime 开始落后于主要的。它缓慢前进,每几分钟几秒钟,最终掉出主要的 oplog 窗口。按照说明 here我在辅助节点上停止了 mongod,删除了所有数据文件,然后重新启动了它,尽管我忘记锁定主节点以防止写入。 Secondary 经历了它的初始化阶段,这花费了大量时间,终于恢复了业务,但是当我登录时,复制现在更落后了。

因为这是云,毕竟我创建了我的主镜像(它应该复制所有数据),尽管当时我无法运行 db.fsyncLock(),因为它需要进行一些写入。新镜像完成后,我基于该镜像启动了一个新服务器,将其添加到我的副本集中,删除旧的辅助节点,然后生活就不错了,对吧?不完全 - 新的次要落后大约一个小时,并且在一天的过程中(和今晚)最终到达落后 14 小时的地步(尽管奇怪的是仍在 oplog 窗口内)。

我从“重新同步过时的成员页面”开始下一步。关闭两台服务器上的 mongod,gzip 并将我的数据文件夹从主要文件夹复制到次要文件夹,解压缩,将它们都启动,db.fsyncLock() 我的主要服务器。让我大吃一惊的是,即使使用相同的数据,在初始化后,我的中学也说它落后了 1 小时。我将它重新添加到副本集中,它很快 catch 落后 5 分钟。

一切都很好,对吧?不 - 向前闪,二级正在缓慢推进,现在落后 20 分钟。 Mongostat 将辅助锁定在 95+ 锁定 %,iostat -xm 2 没有显示任何异常 - 主当前因不进行写入而处于空闲状态,辅助绝对没有做太多事情(0.04 wMB/秒)。不确定是否值得一提,但主要目前感觉登录 mongo shell 的狗响应缓慢,等等。

什么给,蒙戈?为什么你不能 catch ?我在试图让我的中学被 catch 时做错了什么?

编辑
回答问题:

  • 版本:2.0.4
  • 硬件:两个节点都是相同的硬件,据我所知 - 8GB RAM,四核 CPU。我认为这是虚拟化的东西。
  • 写入率:因人而异。如前所述,昨晚我正在转换为一个上限集合,这引发了整个事情。一夜之间,有一个过程每小时写入大约几百个小文档(每个约 155 字节),所以我估计最多大约 100-200kbytes/小时。白天,处理更加密集,更新了数十万个 500 字节的文档,并编写了数十万个文档。仍然没有谈论巨大的数据量。 编辑 发现今天早些时候的一些 iostat 输出:

  • 设备:rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
    xvda 1.00 2564.50 243.50 282.50 8986.00 11388.00 77.47 11.32 21.46 2.36 37.93 0.50 26.50

    那个速度特别快,为 11 wMB/s,7 wMB/s 时 util% 达到 34%,52 rMB/s 时达到 72%。所以没有饱和,但绝对是早上阅读繁重的工作量。有趣的是,尽管有 obj.大小 ~5GB 和 ~1GB 索引(见下文),有太多的磁盘事件。那不应该都在RAM中吗?
  • 工作集:我还没有找到计算工作集的公认方法,但如果有帮助:

  • “集合”:21,
    “对象”:15540092,
    “avgObjSize”:325.26198326238995,
    “数据大小”:5054601144,
    “存储大小”:5874327552,
    “数量范围”:132,
    “索引”:43,
    “索引大小”:864366720,
    “文件大小”:10666115072,
    “nsSizeMB”:16,
    “好的”:1

    我无法想象那是压倒性的 8GB 内存,尽管我可能是错的。
  • 来自中学的一些最近的 mongostat 样本:

  • 插入查询更新删除 getmore 命令刷新映射的 vsize res 故障锁定 % idx 未命中 % qr|qw ar|aw netIn netOut conn set repl time
    *0 *0 *0 *0 0 1|0 0 22.2g 44.9g 912m 0 99.2 0 0|0 0|1 2k 303b 151 mySet SEC 03:47:54
    *0 *0 *0 *0 0 1|0 0 22.2g 44.9g 1.85g 0 101 0 0|0 0|1 3k 303b 151 mySet SEC 03:48:04

    编辑

    尝试了更多的东西。我关闭了主要的(现在称为 A,次要的将是 B),删除了它的数据,并解压了它的快照(现在已经有几个小时了,但此时,我们没有写任何新的东西)。使用 --fastsync 启动 A,它仍然比 B(现在是主要的)运行时间晚 45 秒,后者一直在 02:19:52UTC 左右挂起。最后大约一个小时后,A catch 来,所以我在 B 上调用 rs.stepDown()。 rs.status() 立即向我显示两台服务器在 04:08 UTC 左右都有优化,但 B(现在是次要的)再次滞后17 秒……然后是 30 秒……现在是 7 分钟……

    编辑

    在采纳@matulef 的建议并在我的上限集合上重新创建索引以及重新启动辅助节点的 mongod 进程几分钟后,其运行时间仅增加了几秒钟。来自 mongostat 的二级锁定百分比仍然在 95-104% 之间徘徊,有趣的是,res 大小从 100M 到 2GB 波动很大,然后又回到 1GB 左右。

    编辑(第二天晚上)

    故事的结论 - @matulef 走在正确的轨道上,我应该更加小心地将复制的集合转换为有上限的集合。下面是发生了什么,虽然我没有宣传这是数据安全的 - 我坦率地承认我可能在这个过程中丢失了一些数据,所以 YMMV。

    为主要 (A) 上的上限集合创建索引没有传播到辅助 (B),并且 A 碰巧发生了故障转移(不是故意的)。一旦 B 成为主要的,我就在那里手动创建了上限集合的索引,并使 A 与 B 保持一致的重新同步操作开始快速移动。对我来说不幸的是,我的 oplog 窗口不再排列,所以我最终不得不将数据从 B 快照到 A。一旦我用相同的数据集重新启动 mongo,A 和 B 又高兴了,并且复制又回来了从那以后同步。

    最佳答案

    这里的问题是默认情况下有上限的集合没有 _id 索引(并且“convertToCapped”命令实际上删除了该集合的所有索引)。这是一个问题,因为辅助节点通过应用 oplog 中的操作执行更新,操作通过其 _id 引用文档。如果您缺少 _id 索引,则每次更新都需要对辅助节点进行全表扫描,从而导致它们远远落后。

    解决方案是在上限集合上创建一个 _id 索引。但是,如果您在主服务器上创建索引,但您的辅助服务器已经落后,它们将无法足够快地接收索引创建操作。相反,解决问题的最佳方法是首先一个一个地修复每个滞后的次级。对于每一个,关闭它并以独立模式重新启动(在不同的端口上,没有 --replSet 选项),构建 _id 索引,然后将其添加回集合中。最后,一旦修复了辅助节点,您就可以退出主节点并重复该过程。

    更新 :在 mongoDB 2.0.x 及更早版本中,默认情况下,上限集合没有 _id 索引。但是,默认行为计划在 mongoDB 2.2 中更改,以便在 2.2+ 中创建的上限集合将自动创建 _id 索引,就像非上限集合一样。对于 2.2 之前创建的有上限的集合,您仍然需要使用上述步骤手动创建 _id 索引,但新集合不应遇到上述问题。

    关于mongodb - 为什么我的 MongoDB 副本总是落后?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11424828/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com