从mongodb standalone模式迁移至副本集模式(3.2.x版本)
步骤一:停止所有mongodb读写,否则影响数据同步。
步骤二:创建副本集的mongo实例,将standalone模式的数据库文件拷贝所有副本集实例对应配置文件的dpapth路径中。
注:该操作也可不进行,仅保留主库中数据文件,secoundary节点数据库文件为空,依赖副本集初始化过程的数据自动同步机制,将数据同步到secoundary节点,如果数据库较大,这样操作耗时较长。
步骤三:创建集群用户:
以standalone模式启动mongod实例,用原standalone账号登录mongo shell
执行:use admin
创建有clusterAdmin集群管理权限(副本集、分片、主从等相关管理)的用户
执行:
db.createUser({"user":"dbupdater","pwd":"l79bv2PA","roles":[{role:"root",db:"admin"},{role:"clusterAdmin",db:"admin"}]})
db.auth('dbupdater','l79bv2PA')
步骤四:修改防火墙,开启副本集实例启动所需要的相应端口访问权限
步骤五:mongod配置文件中增加副本集配置
replSet = replTest
注:同一副本集名称相同
步骤六:初始化副本集
使用创建的集群用户登录mongo shell
输入变量:
conf={_id:"replTest", members:[{_id:0, host:'172.28.81.226:27017',priority:2},{_id:1, host:'172.28.81.226:27018'},{_id:2, host:'172.28.81.226:27019'}]}
执行初始化:
rs.initiate(conf)
报错:
{
"ok" : 0,
"errmsg" : "Attempting to initiate a replica set with name rs0, but command line reports replTest; rejecting",
"code" : 93
}
原因:
mongod启动设置的replSet名称与初始化脚本的_id不一致
解决方式:
脚本中_id与配置文件副本集名称相同
报错:
{
"ok" : 0,
"errmsg" : "replSetInitiate quorum check failed because not all proposed set members responded affirmatively: 127.0.0.1:27018 failed with not authorized on admin to execute command { replSetHeartbeat: \"replTest\", pv: 1, v: 1, from: \"127.0.0.1:27017\", fromId: 0, checkEmpty: true }, 127.0.0.1:27019 failed with not authorized on admin to execute command { replSetHeartbeat: \"replTest\", pv: 1, v: 1, from: \"127.0.0.1:27017\", fromId: 0, checkEmpty: true }",
"code" : 74
}
原因:
未配置节点间的免密认证
解决方式:
生成秘钥文件
openssl rand 700 -base64 > /home/config/mongodb.keyfile
chmod 600 /home/config/mongodb.keyfile
将秘钥拷贝到其他服务器(当前实验环境,副本集实例在一台机器不用拷贝):
scp /home/config/mongodb.keyfile root@172.28.81.226:/home/config/
scp /home/config/mongodb.keyfile root@172.28.81.228:/home/config/
在每个实例的配置文件中追加配置项———用于配置节点间的免密验证
在mongod配置文件设置秘钥文件路径
keyFile= /home/replMongo/mongodb.keyfile
报错:
{
"ok" : 0,
"errmsg" : "'172.28.81.226:27018' has data already, cannot initiate set.",
"code" : 110
}
原因:未知
网上有资料说应清空副本集中数据内容,再初始化副本集,保证初始化副本集过程中,secoundary节点没有数据,从主节点同步数据到各secoundary节点
解决方式:
未采用网上方式,改用变更初始化副本集脚本,先初始化一个节点,再将后续副本集节点追加进来。该方式可成功初始化副本集。
变更脚本
conf={_id:"replTest", members:[{_id:0, host:'172.28.81.226:27017'}]}
执行初始化:
rs.initiate(conf)
当前节点被默认为主节点
执行副本集追加操作:
rs.add("172.28.81.226:27018")
rs.add("172.28.81.226:27019")
rs.status()
可以看到后两个从节点stateStr为STARTUP2,正在进行初始化。
观察日志会发现一些索引和数据的同步操作,等待片刻,初始化完成,副本集构建成功。
执行rs.status()
{
"set" : "replTest",
"date" : ISODate("2020-06-15T12:33:54.331Z"),
"myState" : 1,
"term" : NumberLong(1),
"heartbeatIntervalMillis" : NumberLong(2000),
"members" : [
{
"_id" : 0,
"name" : "172.28.81.226:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 2422,
"optime" : {
"ts" : Timestamp(1592224129, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2020-06-15T12:28:49Z"),
"electionTime" : Timestamp(1592224053, 2),
"electionDate" : ISODate("2020-06-15T12:27:33Z"),
"configVersion" : 3,
"self" : true
},
{
"_id" : 1,
"name" : "172.28.81.226:27018",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 334,
"optime" : {
"ts" : Timestamp(1592224129, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2020-06-15T12:28:49Z"),
"lastHeartbeat" : ISODate("2020-06-15T12:33:53.886Z"),
"lastHeartbeatRecv" : ISODate("2020-06-15T12:33:49.524Z"),
"pingMs" : NumberLong(0),
"configVersion" : 3
},
{
"_id" : 2,
"name" : "172.28.81.226:27019",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 304,
"optime" : {
"ts" : Timestamp(1592224129, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2020-06-15T12:28:49Z"),
"lastHeartbeat" : ISODate("2020-06-15T12:33:53.886Z"),
"lastHeartbeatRecv" : ISODate("2020-06-15T12:33:54.015Z"),
"pingMs" : NumberLong(0),
"configVersion" : 3
}
],
"ok" : 1
}