如何确定 STARTUP2 BTree Bottom Up 步骤的整体进度?

How to determine overall progress of the STARTUP2 BTree Bottom Up step?

判断新Secondary member初始同步(STARTUP2)建索引阶段整体进度的好方法是什么?在我的案例中,索引构建阶段需要很长时间(几天),如果能够看到它在这个过程中的哪个阶段,那就太好了。

日志输出如下所示:

Tue Jan 27 20:04:45.006 [rsSync]    Index: (2/3) BTree Bottom Up Progress: 782212700/946547617  82%

就我而言,这意味着“82% 的对象,未知数量的未知大小的对象。”

目前没有监控此进度的方法,尽管有一张票可以使用 rs.status():

加强对 STARTUP2 的监控

https://jira.mongodb.org/browse/SERVER-7526 https://jira.mongodb.org/browse/SERVER-7019

也就是说,这个阶段所需的时间大致是每个索引所需时间乘以索引数量的函数。反过来,每个索引所需的时间是每个索引中文档数量的函数。

因此,如果您测量创建索引所需的时间,请将其除以该索引中的文档总数。这应该让您大致了解索引单个文档的速度。然后将其乘以所有索引中的文档总数,您应该可以了解剩余时间。

现在,这是一个粗略的想法 - 影响总时间的一件事是需要索引的数据的总大小与可用内存的关系。如果你必须创建一个索引,在创建另一个涉及相同文档的索引之后,如果数据仍然缓存在内存中,它可能会更快一些。没有办法很容易地预测这一点,除了说如果总文档大小 >> 比内存那么你不会看到由于以前的文档缓存而有太多加速。

从长远来看,我会投赞成票 https://jira.mongodb.org/browse/SERVER-7019 看看我们是否不能将它放入队列中,因为对于大型 MongoDB 数据库来说,不使用它真的很痛苦。

现在可以修复 SERVER-7526 and SERVER-7019

MongoDB 4.2.1及以上:

运行 在 mongo shell 中: db.adminCommand( { replSetGetStatus: 1 } )

If you run replSetGetStatus or the mongo shell helper rs.status() on a member during its initial sync (i.e. STARTUP2 state), the command returns replSetGetStatus.initialSyncStatus metrics.

这是 initialSyncStatus 的示例输出:

        "initialSyncStatus" : {                                       
                "failedInitialSyncAttempts" : 0,                            
                "maxFailedInitialSyncAttempts" : 10,                                 
                "initialSyncStart" : ISODate("2019-10-29T20:01:12.516Z"),                                      
                "initialSyncAttempts" : [ ],                                       
                "fetchedMissingDocs" : 0,                                     
                "appliedOps" : 0,                                                                              
                "initialSyncOplogStart" : Timestamp(1572379269, 4),                
                "databases" : {                                                                                
                        "databasesCloned" : 3,                     
                        "admin" : {                           
                                "collections" : 4,                                    
                                "clonedCollections" : 4,                            
                                "start" : ISODate("2019-10-29T20:01:13.393Z"),
                                "end" : ISODate("2019-10-29T20:01:14.777Z"),
                                "elapsedMillis" : 1384,         
                                "admin.system.roles" : {                      
                                        "documentsToCopy" : 1,                                                 
                                        "documentsCopied" : 1,                   
                                        "indexes" : 2,                        
                                        "fetchedBatches" : 1,                         
                                        "start" : ISODate("2019-10-29T20:01:13.911Z"),
                                        "end" : ISODate("2019-10-29T20:01:14.196Z"),
                                        "elapsedMillis" : 285                    
                                }, 

MongoDB 3.4.0 - 4.2.0:

执行 db.adminCommand( { replSetGetStatus: 1, initialSync: 1 } ) 对处于 STARTUP2 状态的成员发出命令

MongoDB 参考: replSetGetStatus

回答 MongoDB 5.0 版本

初始同步可能需要一些时间 - 请耐心等待。据我所知,它分两步 运行s。首先 MongoDB 克隆所有集合,即它制作所有集合的“普通”副本。您可以通过连接到同步成员和 运行 rs.status().initialSyncStatus

来监控这一点
shard_03:STARTUP2> rs.status().initialSyncStatus
{
        "failedInitialSyncAttempts" : 0,
        "maxFailedInitialSyncAttempts" : 10,
        "initialSyncStart" : ISODate("2022-04-28T08:33:36.519Z"),
        "totalInitialSyncElapsedMillis" : 6548240,
        "initialSyncAttempts" : [ ],
        "approxTotalDataSize" : NumberLong("488957278026"),
        "approxTotalBytesCopied" : NumberLong("519033102224"),
        "remainingInitialSyncEstimatedMillis" : -379443,
        "appliedOps" : 0,
        "initialSyncOplogStart" : Timestamp(1651134817, 16004),
        "totalTimeUnreachableMillis" : NumberLong(0),
        "databases" : {
                "databasesToClone" : 2,
                "databasesCloned" : 5,
...
                "plau01mipmed0" : {
                        "collections" : 9,
                        "clonedCollections" : 8,
                        "start" : ISODate("2022-04-28T09:56:10.907Z"),
                        "plau01mipmed0.sessions" : {
                                "documentsToCopy" : 16449103,
                                "documentsCopied" : 16891103,
                                "indexes" : 4,
                                "fetchedBatches" : 242,
                                "bytesToCopy" : NumberLong("3816816827"),
                                "approxBytesCopied" : NumberLong("3918735896"),
                                "start" : ISODate("2022-04-28T09:56:10.907Z"),
                                "end" : ISODate("2022-04-28T09:59:02.068Z"),
                                "elapsedMillis" : 171161,
                                "receivedBatches" : 242
                        },
                        "plau01mipmed0.ignored" : {
                                "documentsToCopy" : 8095615,
                                "documentsCopied" : 5711111,
                                "indexes" : 2,
                                "fetchedBatches" : 86,
                                "bytesToCopy" : 1966181814,
                                "approxBytesCopied" : 1382088862,
                                "start" : ISODate("2022-04-28T10:22:17.332Z"),
                                "receivedBatches" : 86
                        }

一段时间后你应该得到类似

的结果
shard_03:STARTUP2> rs.status().initialSyncStatus.databases    
...
{ 
  ... 
  "databases" : { 
    "databasesToClone" : 0, 
    "databasesCloned" : 7
    }
}

之后MongoDB开始应用oplog。您可以使用此命令对其进行监控:

shard_03:STARTUP2> rs.status().members.filter(x => x.name == db.hello().me).forEach(
   x => printjson(
      {
         date: ISODate(),
         name: x.name,
         stateStr: x.stateStr,
         optimeDate: x.optimeDate,
         oplog_BacklogSeconds: (ISODate() - x.optimeDate) / 1000
      }
   )
)

{
   "date" : ISODate("2022-04-28T11:27:42.111Z"),
   "name" : "d-mipmdb-sh2-03:27018",
   "stateStr" : "STARTUP2",
   "optimeDate" : ISODate("2022-04-28T09:40:50Z"),
   "oplog_BacklogSeconds" : 6412.111
}

同样,您需要耐心等待。 oplog_BacklogSeconds 应该 慢慢地 减少。但是,当您 运行 rs.status().initialSyncStatus.appliedOps 时,您会看到不断增加的数字。

成员国迟早要到SECONDARY。由于这次同步还没有完全完成,即 oplog_BacklogSeconds 可能仍然显示很高的数字,但它应该会下降得相当快。当它变成1-2秒时就完全完成了。