1. 准备工作
有一套mongodb 副本集的集群,部署方式参考 mongodb 4.0副本集搭建
准备一个新节点,使用和原副本集版本一致的mongodb
拷贝原副本集中的配置文件、keyfile文件,并注意修改keyfile文件的权限(600)
节点 |
角色 |
192.168.56.199:27017 | PRIMARY |
192.168.56.198:27018 | SECONDARY |
192.168.56.199:27018 | ARBITER |
准备加入的新节点: 192.168.56.197:27017
2. 添加节点
2.1 启动新节点
例如,原节点的版本是4.2.8,新节点版本一致,路径一致,然后启动新节点
/usr/local/mongodb/bin/mongod -f /data/mongodb/27017/etc/mongodb.conf
2.2 主库上查看当前节点及配置信息
使用rs.config()查看配置信息
test12:PRIMARY> rs.config() { "_id" : "test12", "version" : 1, "protocolVersion" : NumberLong(1), "writeConcernMajorityJournalDefault" : true, "members" : [ { "_id" : 0, "host" : "192.168.56.198:27017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 1, "host" : "192.168.56.199:27017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 2, "host" : "192.168.56.199:27018", "arbiterOnly" : true, "buildIndexes" : true, "hidden" : false, "priority" : 0, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 } ], "settings" : { "chainingAllowed" : true, "heartbeatIntervalMillis" : 2000, "heartbeatTimeoutSecs" : 10, "electionTimeoutMillis" : 10000, "catchUpTimeoutMillis" : -1, "catchUpTakeoverDelayMillis" : 30000, "getLastErrorModes" : { }, "getLastErrorDefaults" : { "w" : 1, "wtimeout" : 0 }, "replicaSetId" : ObjectId("61b86af0a21015e69623e18d") } }
rs.status() 查看状态信息
test12:PRIMARY> rs.status() { "set" : "test12", "date" : ISODate("2021-12-14T10:07:46.561Z"), "myState" : 1, "term" : NumberLong(1), "syncingTo" : "", "syncSourceHost" : "", "syncSourceId" : -1, "heartbeatIntervalMillis" : NumberLong(2000), "majorityVoteCount" : 2, "writeMajorityCount" : 2, "optimes" : { "lastCommittedOpTime" : { "ts" : Timestamp(1639476462, 1), "t" : NumberLong(1) }, "lastCommittedWallTime" : ISODate("2021-12-14T10:07:42.560Z"), "readConcernMajorityOpTime" : { "ts" : Timestamp(1639476462, 1), "t" : NumberLong(1) }, "readConcernMajorityWallTime" : ISODate("2021-12-14T10:07:42.560Z"), "appliedOpTime" : { "ts" : Timestamp(1639476462, 1), "t" : NumberLong(1) }, "durableOpTime" : { "ts" : Timestamp(1639476462, 1), "t" : NumberLong(1) }, "lastAppliedWallTime" : ISODate("2021-12-14T10:07:42.560Z"), "lastDurableWallTime" : ISODate("2021-12-14T10:07:42.560Z") }, "lastStableRecoveryTimestamp" : Timestamp(1639476442, 1), "lastStableCheckpointTimestamp" : Timestamp(1639476442, 1), "electionCandidateMetrics" : { "lastElectionReason" : "electionTimeout", "lastElectionDate" : ISODate("2021-12-14T09:59:22.407Z"), "electionTerm" : NumberLong(1), "lastCommittedOpTimeAtElection" : { "ts" : Timestamp(0, 0), "t" : NumberLong(-1) }, "lastSeenOpTimeAtElection" : { "ts" : Timestamp(1639475952, 1), "t" : NumberLong(-1) }, "numVotesNeeded" : 2, "priorityAtElection" : 1, "electionTimeoutMillis" : NumberLong(10000), "numCatchUpOps" : NumberLong(0), "newTermStartDate" : ISODate("2021-12-14T09:59:22.431Z"), "wMajorityWriteAvailabilityDate" : ISODate("2021-12-14T09:59:23.493Z") }, "members" : [ { "_id" : 0, "name" : "192.168.56.198:27017", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 514, "optime" : { "ts" : Timestamp(1639476462, 1), "t" : NumberLong(1) }, "optimeDurable" : { "ts" : Timestamp(1639476462, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2021-12-14T10:07:42Z"), "optimeDurableDate" : ISODate("2021-12-14T10:07:42Z"), "lastHeartbeat" : ISODate("2021-12-14T10:07:45.153Z"), "lastHeartbeatRecv" : ISODate("2021-12-14T10:07:46.542Z"), "pingMs" : NumberLong(1), "lastHeartbeatMessage" : "", "syncingTo" : "192.168.56.199:27017", "syncSourceHost" : "192.168.56.199:27017", "syncSourceId" : 1, "infoMessage" : "", "configVersion" : 1 }, { "_id" : 1, "name" : "192.168.56.199:27017", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 1001, "optime" : { "ts" : Timestamp(1639476462, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2021-12-14T10:07:42Z"), "syncingTo" : "", "syncSourceHost" : "", "syncSourceId" : -1, "infoMessage" : "", "electionTime" : Timestamp(1639475962, 1), "electionDate" : ISODate("2021-12-14T09:59:22Z"), "configVersion" : 1, "self" : true, "lastHeartbeatMessage" : "" }, { "_id" : 2, "name" : "192.168.56.199:27018", "health" : 1, "state" : 7, "stateStr" : "ARBITER", "uptime" : 514, "lastHeartbeat" : ISODate("2021-12-14T10:07:44.896Z"), "lastHeartbeatRecv" : ISODate("2021-12-14T10:07:44.896Z"), "pingMs" : NumberLong(0), "lastHeartbeatMessage" : "", "syncingTo" : "", "syncSourceHost" : "", "syncSourceId" : -1, "infoMessage" : "", "configVersion" : 1 } ], "ok" : 1, "$clusterTime" : { "clusterTime" : Timestamp(1639476462, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } }, "operationTime" : Timestamp(1639476462, 1) }
2.3 将新节点添加至集群
在主库上执行rs.add()将新节点添加进集群中
生产环境添加节点时,建议将priority及votes设为0,即不会选为主(priority默认1),也没有投票特性(votes默认1,有投票权)
test12:PRIMARY> rs.add( { host: "192.168.56.197:27017", priority: 0, votes: 0 } ) { "ok" : 1, "$clusterTime" : { "clusterTime" : Timestamp(1639476997, 1), "signature" : { "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="), "keyId" : NumberLong(0) } }, "operationTime" : Timestamp(1639476997, 1) }
另外,生产环境是从主库拉取全量数据,如果数据量较大,则需要观察主库的压力及对线上业务的影响。
同步数据的过程中,新节点的状态stateStr 为STARTUP2,待同步完成后会变为SECONDARY。
2.4 重置新节点的属性
此时再用rs.config()查看新节点状态,priority及votes是之前设的0,可以使用 rs.recofig()命令进行调整
test12:PRIMARY> rs.config() { "_id" : "test12", "version" : 2, "protocolVersion" : NumberLong(1), "writeConcernMajorityJournalDefault" : true, "members" : [ { "_id" : 0, "host" : "192.168.56.198:27017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 1, "host" : "192.168.56.199:27017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 2, "host" : "192.168.56.199:27018", "arbiterOnly" : true, "buildIndexes" : true, "hidden" : false, "priority" : 0, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 3, "host" : "192.168.56.197:27017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 0, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 0 } ], "settings" : { "chainingAllowed" : true, "heartbeatIntervalMillis" : 2000, "heartbeatTimeoutSecs" : 10, "electionTimeoutMillis" : 10000, "catchUpTimeoutMillis" : -1, "catchUpTakeoverDelayMillis" : 30000, "getLastErrorModes" : { }, "getLastErrorDefaults" : { "w" : 1, "wtimeout" : 0 }, "replicaSetId" : ObjectId("61b86af0a21015e69623e18d") } }
从上面可以看到新节点的id为3 ,则可以通过如下命令调整对应的属性
var cfg = rs.conf() cfg.members[3].priority = 1 cfg.members[3].votes = 1 rs.reconfig(cfg)
调整后再查看,属性已调整
test12:PRIMARY> rs.config() { "_id" : "test12", "version" : 3, "protocolVersion" : NumberLong(1), "writeConcernMajorityJournalDefault" : true, "members" : [ { "_id" : 0, "host" : "192.168.56.198:27017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 1, "host" : "192.168.56.199:27017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 2, "host" : "192.168.56.199:27018", "arbiterOnly" : true, "buildIndexes" : true, "hidden" : false, "priority" : 0, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 }, { "_id" : 3, "host" : "192.168.56.197:27017", "arbiterOnly" : false, "buildIndexes" : true, "hidden" : false, "priority" : 1, "tags" : { }, "slaveDelay" : NumberLong(0), "votes" : 1 } ], "settings" : { "chainingAllowed" : true, "heartbeatIntervalMillis" : 2000, "heartbeatTimeoutSecs" : 10, "electionTimeoutMillis" : 10000, "catchUpTimeoutMillis" : -1, "catchUpTakeoverDelayMillis" : 30000, "getLastErrorModes" : { }, "getLastErrorDefaults" : { "w" : 1, "wtimeout" : 0 }, "replicaSetId" : ObjectId("61b86af0a21015e69623e18d") } }
至此,新节点便加入了副本集中
3. 注意点总结
-
一个副本集,最多可以拥有50个secondary,最多可以有7个投票成员,在副本集里面添加一个新成员,如果之前副本集已经有了7个成员,那么可以设置成非投票成员,或者你从移除之前一个投票成员出来
-
新节点的版本、配置建议与原集群一致
-
注意添加新节点前确定网络互通
-
如果集群数据量较大,则选择业务低峰期添加节点,并观察压力情况
-
新节点加入时建议将priority及votes设为0