为什么我的MongoDB副本不断落后?

aws*_*ard 10 replication mongodb

虽然昨晚将收藏品转换为封顶收藏品,但我的次要运动时间开始落后于初级.它进展缓慢,每隔几分钟几秒钟,最终落在主要的oplog窗口之外.根据这里的说明,我在次要文件上停止了mongod,删除了所有数据文件,然后重新启动它,尽管我忘了将主文件从写入锁定.辅助设备经历了初始阶段,这需要花费大量时间,最终重新开始运营,但是当我登录时,复制现在甚至更远了.

因为这是云,毕竟我创建了一个我的主映像(它应该复制所有数据),虽然我当时无法运行db.fsyncLock(),因为它正在进行一些写操作.新图像完成,我基于该图像启动一个新的服务器,将它添加到我的副本集,删除旧的二级,生活是好的,对吧?不完全 - 新的中学落后了大约一个小时,并且在一天中(和今晚)最终达到了落后14小时的程度(尽管在oplog窗口内仍然非常奇怪).

我从"重新同步一个陈旧的成员页面"迈出了下一步.关闭两台服务器上的mongod,gzip并将我的数据文件夹从主数据库复制到辅助服务器,解压缩,将它们都解压缩,db.fsyncLock()我的主服务器.令我震惊的是,即使使用相同数据,在初始化之后,我的中学也说它落后了1个小时.我将它添加回副本集中,并迅速赶上落后5分钟.

一切都好,对吗?不 - 闪现前锋,中学正在向前推进,现在落后20分钟.Mongostat次要挂钩95%锁定%,iostat -xm 2没有显示任何疯狂 - 主要目前因不接受写入而空闲,次要绝对没有做多少(.04 wMB /秒).不确定它是否值得一提,但是主要目前感觉狗慢慢反应无法登录到mongo shell等.

什么给,Mongo?为什么你不能赶上?我试图让我的二手陷入困境我做错了什么?

编辑 回答问题:

  • 版本:2.0.4
  • 硬件:两个节点都是相同的硬件,接近我所知 - 8GB RAM,四核CPU.我认为这是虚拟化的东西.
  • 写入率:它有所不同.如上所述,昨晚我转换为一个上限集合,触发了整个事情.一夜之间,有一个过程每小时写几百个小文件(每个大约155个字节),所以最大估计大约100-200kbytes /小时.在白天,处理更加激烈,更新了数十万个500字节的文档,并写了几十万个文档.仍然没有谈论庞大的数据量.EDIT今天早些时候发现了一些iostat输出:
Device:         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的速度特别突破,实用率达到34%,7 wMB/s,72%达到52 rMB/s.所以没有饱和,但绝对是早上读取繁重的工作量.尽管有obj,但它很有趣.大小~5GB,和~1GB索引(见下文),磁盘活动太多了.难道不应该都在内存中吗?

  • 工作集:我还没有找到计算工作集的公认方法,但如果它有帮助:
    "collections" : 21,
    "objects" : 15540092,
    "avgObjSize" : 325.26198326238995,
    "dataSize" : 5054601144,
    "storageSize" : 5874327552,
    "numExtents" : 132,
    "indexes" : 43,
    "indexSize" : 864366720,
    "fileSize" : 10666115072,
    "nsSizeMB" : 16,
    "ok" : 1

我无法想象那是8GB的压倒性内存,尽管我可能错了.

  • 最近的一些mongostat样本来自中学:
insert  query update delete getmore command flushes mapped  vsize    res faults locked % idx miss %     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,它仍然比B(现在的主要)optime落后45秒,它在02:19:52UTC时已经停止了.最后大约一个小时后,A赶上,所以我在B上调用rs.stepDown().当然,rs.status()告诉我两台服务器在04:08 UTC时都有运行时间,但B(现在是次要的)再次落后17秒......然后30秒......现在7分钟......

编辑

在获取@matulef的建议并在我的上限集合上重新创建索引以及重新启动二级mongod进程几分钟后,其optime仅增加了几秒钟.来自mongostat的次要锁定%仍然在95-104%之间徘徊,有趣的是,res大小从100M大幅摆动到2GB并再次回落,然后再稳定在1GB左右.

编辑(第二天晚上)

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

为主(A)上的上限集合创建索引不会传播到辅助(B),而A恰好是故障转移(非故意).一旦B是主要的,我手动在那里的上限集合上创建索引,并且使A与B一致的再同步操作开始快速移动.不幸的是,我的oplog窗口不再排队,所以我最终不得不将数据从B快照到A.一旦我用相同的数据集重新启动mongo,A&B再次开心,并且复制已经恢复从那时起同步.

mat*_*lef 6

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

解决方案是在上限集合上创建_id索引.但是,如果您在主服务器上创建索引,但是您的辅助服务器已经落后,那么它们将不会足够快地接收索引创建操作.相反,解决问题的最佳方法是首先逐个修复每个滞后的辅助设备.对于每一个,将其关闭并以独立模式重新启动(在不同的端口上,不使用--replSet选项),构建_id索引,然后将其添加回集合中.最后,一旦修复了辅助副本,您就可以降低主要部分,并使用它重复该过程.

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