【问题标题】:How to migrate from MMAPv1 to WiredTiger with minimal downtime without mongodump/mongorestore如何在没有 mongodump/mongorestore 的情况下以最短的停机时间从 MMAPv1 迁移到 WiredTiger
【发布时间】:2017-01-31 14:55:56
【问题描述】:

大多数指南建议使用 mongodump/mongorestore,但对于大型产品数据库,停机时间可能会很长

【问题讨论】:

    标签: mongodb replication wiredtiger database


    【解决方案1】:

    如果负载允许,您可以为此或同一台服务器使用复制和附加服务器。

    1. 您需要 3 个正在运行的 MongoDB 实例:

      • 您要更新的服务器(提醒 WiredTiger 自 3.0 起支持)。
      • MongoDB 的第二个实例,可以在附加服务器上运行。数据库将通过复制临时复制到其中。
      • 而MongoDB的第三个实例是arbiter,它不存储数据,只参与主服务器的选举。仲裁器可以在单独端口上的附加服务器上运行。
    2. 无论如何,您都需要备份您的数据库。您可以不带参数运行“mongodump”,并且将使用数据库转储创建目录“./dump”。您可以使用“--gzip”参数来压缩结果大小。

      mongodump --gzip
      

      以防万一,恢复命令:

      mongorestore --gzip
      

      如果在“mongodump”中使用,应该在“./dump”目录和“--gzip”参数的同一目录下运行”。

    3. 从附加服务器开始配置。我的目标系统是没有网络的Linux RedHat,所以我通过RPM手动下载并安装了MongoDB。将该部分添加到 /etc/mongod.conf

      replication:
         oplogSizeMB: 10240
         replSetName: REPLICA  
      

      检查 net 部分是否如下所示,以允许其他服务器访问:

      net:
        bindIp: 0.0.0.0
        port: 27017
      

      然后运行:

      service mongod start
      
    4. 运行第三个 MongoDB 实例 - 仲裁器。它可以在不同端口上的附加服务器上工作。为仲裁数据库创建一个临时目录:

      mkdir /tmp/mongo
      chmod 777 -R /tmp/mongo
      

      然后运行:

      mongod --dbpath /tmp/mongo --port 27001 --replSet REPLICA \
          --fork --logpath /tmp/mongo/db1.log
      
    5. 现在配置主服务器。编辑 /etc/mongod.conf

      replication:
         oplogSizeMB: 10240
         replSetName: REPLICA   
      

      并在主服务器上重启 MongoDB:

      service mongod restart
      
    6. 这很重要!重启后主服务器读取操作可能不可用。我收到以下错误:

      { "ok" : 0, "errmsg" : "node is recovering", "code" : 13436 }
      

      所以您需要尽快通过“mongo”控制台连接到主服务器上的 MongoDB 并运行以下命令来配置复制:

      rs.initiate(
      {
        _id: "REPLICA",
        members: [
          { _id: 0, host : "<IP address of main server>:27017",
                    priority: 1.0 },
          { _id: 1, host : "<IP  address of additional server>:27017",
                    priority: 0.5 },
          { _id: 2, host : "<IP address of additional server(the arbiter)>:27001", 
                    arbiterOnly : true,  priority: 0.5  }
        ]
      }
      )
      

      在此操作之后,所有与 MongoDB 的操作都将可用,并且将开始数据同步。

      我不建议像大多数教程那样在没有参数的主服务器上使用 rs.initiate(),因为主服务器的名称将默认配置为来自/etc/主机名。这对我来说不是很方便,因为我在项目中使用 IP 地址进行通信。

      要检查同步进度,您可以从“mongo”控制台调用:

      rs.status()
      

      结果示例:

      {
         "set" : "REPLICA",
         "date" : ISODate("2017-01-19T14:30:34.292Z"),
         "myState" : 1,
         "term" : NumberLong(1),
         "heartbeatIntervalMillis" : NumberLong(2000),
         "members" : [
             {
                 "_id" : 0,
                 "name" : "<IP address of main server>:27017",
                 "health" : 1.0,
                 "state" : 1,
                 "stateStr" : "PRIMARY",
                 "uptime" : 165,
                 "optime" : {
                     "ts" : Timestamp(6377323060650835, 3),
                     "t" : NumberLong(1)
                 },
                 "optimeDate" : ISODate("2017-01-19T14:30:33.000Z"),
                 "infoMessage" : "could not find member to sync from",
                 "electionTime" : Timestamp(6377322974751490, 1),
                 "electionDate" : ISODate("2017-01-19T14:30:13.000Z"),
                 "configVersion" : 1,
                 "self" : true
             },
             {
                 "_id" : 1,
                 "name" : "<IP address of additional server>:27017",
                 "health" : 1.0,
                 "state" : 5,
                 "stateStr" : "STARTUP2",
                 "uptime" : 30,
                 "optime" : {
                     "ts" : Timestamp(0, 0),
                     "t" : NumberLong(-1)
                 },
                 "optimeDate" : ISODate("1970-01-01T00:00:00.000Z"),
                 "lastHeartbeat" : ISODate("2017-01-19T14:30:33.892Z"),
                 "lastHeartbeatRecv" : ISODate("2017-01-19T14:30:34.168Z"),
                 "pingMs" : NumberLong(3),
                 "syncingTo" : "<IP address of main server>:27017",
                 "configVersion" : 1
             },
             {
                 "_id" : 2,
                 "name" : "<IP address of additional server (the arbiter)>:27001",
                 "health" : 1.0,
                 "state" : 7,
                 "stateStr" : "ARBITER",
                 "uptime" : 30,
                 "lastHeartbeat" : ISODate("2017-01-19T14:30:33.841Z"),
                 "lastHeartbeatRecv" : ISODate("2017-01-19T14:30:30.158Z"),
                 "pingMs" : NumberLong(0),
                 "configVersion" : 1
             }
         ],
         "ok" : 1.0
      }
      

      附加服务器的“stateStr”将从“STARTUP2”替换为“SECONDARY”后,我们的服务器将同步。

    7. 在我们等待同步结束时,有必要稍微修改客户端应用程序,它们可以与副本中的所有服务器一起使用。

      • 如果您使用 ConnectionString,则应将其替换为:

        mongodb://<IP address of main server>:27017,<IP address of additional server>:27017,<IP address of additional server (the arbiter)>:27001/?replicaSet=REPLICA
        
      • 如果你像我一样使用 C++ mongo-cxx-driver legacy,你应该使用 mongo::DBClientReplicaSet 而不是 mongo::DBClientConnection 并列出连接参数中的所有三个服务器,包括仲裁器。

      • 还有第三种选择——切换PRIMARY-SECONDARY后,可以简单地在客户端更改MongoDB服务器的IP,但这不太公平。 p>

    8. 在同步结束并且一个额外的服务器状态建立为SECONDARY之后,我们需要通过执行主服务器上的“mongo”控制台中的命令。这很重要,因为命令不会在附加服务器上运行。

      cfg = rs.conf()
      cfg.members[0].priority = 0.5
      cfg.members[1].priority = 1
      cfg.members[2].priority = 0.5
      rs.reconfig(cfg)
      

      然后通过执行检查服务器状态:

      rs.status()
      
    9. 在主服务器上停止 MongoDB

      service mongod stop
      

      然后简单地删除带有数据库的目录的全部内容。这是安全的,因为我们在附加服务器上有一个工作副本,并且一开始我们已经做了备份。当心。 MongoDB 本身不会创建数据库目录。如果你已经删除了,你不仅需要恢复

      mkdir /var/lib/mongo
      

      和设置所有者:

      chown -R mongod:mongod /var/lib/mongo
      
    10. 检查存储引擎wiredTiger是否在/etc/mongod.conf中配置。从 3.2 开始默认使用:

      storage:
           ...
          engine: wiredTiger
          ...
      

      然后运行 ​​MongoDB:

      service mongod start
      

      主服务器会自动从辅助服务器获取配置,并将数据同步回WiredTiger存储。

    11. 同步完成后,切换回 PRIMARY 服务器。此操作应在另一台服务器上执行,因为它现在是 PRIMARY

      cfg = rs.conf()
      cfg.members[0].priority = 1
      cfg.members[1].priority = 0.5
      cfg.members[2].priority = 0.5
      rs.reconfig(cfg)
      
    12. 返回旧版本的数据库客户端或改回ConnectionString

    13. 如果需要,现在关闭复制。从主服务器中移除 2 个复制服务器:

      rs.remove("<IP address of additional server>:27017")
      rs.remove("<IP address of additional server (the arbiter)>:27001")
      

      /etc/mongod.conf 中删除所有“replication”部分并重新启动 MongoDB:

      service mongod restart
      

      在这些之后,我们在通过“mongo”控制台连接时收到警告:

      2017-01-19T12:26:51.948+0300 I STORAGE  [initandlisten] ** WARNING: mongod started without --replSet yet 1 documents are present in local.system.replset
      2017-01-19T12:26:51.948+0300 I STORAGE  [initandlisten] **          Restart with --replSet unless you are doing maintenance and  no other clients are connected.
      2017-01-19T12:26:51.948+0300 I STORAGE  [initandlisten] **          The TTL collection monitor will not start because of this.
      

      要摆脱它,您需要删除数据库“local”。默认状态下,该数据库中只有一个集合“startup_log”,因此您可以通过“mongo”控制台进行操作

      use local
      db.dropDatabase()
      

      然后重启 MongoDB:

      service mongod restart
      

      如果您从 /etc/mongod.conf 中删除“replication”部分之前的“local”数据库,它会立即恢复.所以我不能只重启一次 MongoDB。

    14. 在其他服务器上执行相同的操作:

      • /etc/mongod.conf 中删除“复制”部分
      • 重启 MongoDB
      • 删除“本地”数据库
      • 再次重启
    15. 仲裁者只是停止并移除:

      pkill -f /tmp/mongo
      rm -r /tmp/mongo
      

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-13
      • 1970-01-01
      • 2020-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-24
      • 2016-03-08
      相关资源
      最近更新 更多