|
1、修改配置文件
基本配置如下:
systemLog:
destination: file
logAppend: true
path: /var/log/mongodb/mongod.log
logRotate: rename
storage:
dbPath: /data/db
journal:
enabled: true
engine: wiredTiger
processManagement:
fork: true # fork and run in background
pidFilePath: /usr/local/mongodb/mongod.pid # location of pidfile
net:
port: 27017
bindIp: x.x.x.x # Listen to local interface only, comment to listen on all interfaces.
http:
enabled: false
RESTInterfaceEnabled: false
#security:
# authorization: enabled
在基本配置的基础上对三台mongodb的配置文件统一添加如下:
replication:
oplogSizeMB: 20
replSetName: Myrepl
注:oplogSizeMB指oplog大小,即复制操作日志的最大大小(以兆字节为单位
replSetName 指副本集名称,注意格式是前面空两格,冒号后空一格。
然后重启三台MongoDB的mongod进程!
#killall mongod
#su mongod -c "/usr/local/mongodb/bin/mongod -f /etc/mongod.conf" #以普通用户启动
2、在主服务器操作
#mongo --host 10.0.18.144
MongoDB shell version v3.4.2
connecting to: mongodb://10.0.18.144:27017/
MongoDB server version: 3.4.2
> use admin
switched to db admin
> config={_id:"Myrepl",members:[{_id:0,host:"10.0.18.144:27017"},{_id:1,host:"10.0.18.149:27017"},{_id:2,host:"10.0.18.150:27017"}]}config={_id:"Myrepl",members:[{_id:0,host:"10.0.18.144:27017"},{_id:1,host:"10.0.18.149:27017"},{_id:2,host:"10.0.18.150:27017"}]}
{
"_id" : "Myrepl",
"members" : [
{
"_id" : 0,
"host" : "10.0.18.144:27017"
},
{
"_id" : 1,
"host" : "10.0.18.149:27017"
},
{
"_id" : 2,
"host" : "10.0.18.150:27017"
}
]
}
> rs.initiate(config) #初始化
{ "ok" : 1 } #显示ok表示成功
Myrepl:OTHER>
补充:要想使用副本集,从的mongodb的数据必须都是空的,要不然执行rs.initiate()命令时会提示因
存在数据而导致初始化不成功,如下:
> rs.initiate(config)
{
"ok" : 0,
"errmsg" : "'10.0.18.150:27017' has data already, cannot initiate set.",
"code" : 110,
"codeName" : "CannotInitializeNodeWithData"
}
继续进行:
Myrepl:OTHER> rs.status() #查看副本集状态
{
"set" : "Myrepl",
"date" : ISODate("2017-02-16T08:57:54.003Z"),
"myState" : 1,
"term" : NumberLong(1),
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1487235464, 1),
"t" : NumberLong(1)
},
"appliedOpTime" : {
"ts" : Timestamp(1487235464, 1),
"t" : NumberLong(1)
},
"durableOpTime" : {
"ts" : Timestamp(1487235464, 1),
"t" : NumberLong(1)
}
},
"members" : [
{
"_id" : 0,
"name" : "10.0.18.144:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY", #主
"uptime" : 941,
"optime" : {
"ts" : Timestamp(1487235464, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2017-02-16T08:57:44Z"),
"electionTime" : Timestamp(1487235294, 1),
"electionDate" : ISODate("2017-02-16T08:54:54Z"),
"configVersion" : 1,
"self" : true
},
{
"_id" : 1,
"name" : "10.0.18.149:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY", #从
"uptime" : 191,
"optime" : {
"ts" : Timestamp(1487235464, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1487235464, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2017-02-16T08:57:44Z"),
"optimeDurableDate" : ISODate("2017-02-16T08:57:44Z"),
"lastHeartbeat" : ISODate("2017-02-16T08:57:52.541Z"),
"lastHeartbeatRecv" : ISODate("2017-02-16T08:57:52.182Z"),
"pingMs" : NumberLong(0),
"syncingTo" : "10.0.18.150:27017",
"configVersion" : 1
},
{
"_id" : 2,
"name" : "10.0.18.150:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY", #从
"uptime" : 191,
"optime" : {
"ts" : Timestamp(1487235464, 1),
"t" : NumberLong(1)
},
"optimeDurable" : {
"ts" : Timestamp(1487235464, 1),
"t" : NumberLong(1)
},
"optimeDate" : ISODate("2017-02-16T08:57:44Z"),
"optimeDurableDate" : ISODate("2017-02-16T08:57:44Z"),
"lastHeartbeat" : ISODate("2017-02-16T08:57:52.542Z"),
"lastHeartbeatRecv" : ISODate("2017-02-16T08:57:52.092Z"),
"pingMs" : NumberLong(0),
"syncingTo" : "10.0.18.144:27017",
"configVersion" : 1
}
],
"ok" : 1
}
注意:两个从上的状态为 "stateStr" : "SECONDARY",若为 "STARTUP",则需要进行如下操作:
> var config={_id:"tpp",members:[{_id:0,host:"192.168.0.103:27017"},{_id:1,host:"192.168.0.109:27017"},{_id:2,host:"192.168.0.120:27017"}]}
> rs.initiate(config)
查看到以上信息就说明配置成功了,我们也会发现主上前缀变为Myrepl:PRIMARY> 而从服务器的前缀
变成了Myrepl:SECONDARY>
3、副本集测试
在主服务器上建库、建集合、插入数据
Myrepl:PRIMARY> use testdb
switched to db testdb
Myrepl:PRIMARY> db.createCollection('test1')
{ "ok" : 1 }
Myrepl:PRIMARY> show dbs
admin 0.000GB
local 0.000GB
testdb 0.000GB
Myrepl:PRIMARY> db.testdb.insert({"name":"repl","time":"170216"}) #插入一条数据
WriteResult({ "nInserted" : 1 })
Myrepl:PRIMARY> db.testdb.findOne() #查看数据
{
"_id" : ObjectId("58a56b7404b33bc093a90321"),
"name" : "repl",
"time" : "170216"
}
然后再从服务器上查看
#mongo --host 10.0.18.149
MongoDB shell version v3.4.2
connecting to: mongodb://10.0.18.149:27017/
MongoDB server version: 3.4.2
Myrepl:SECONDARY> show dbs
2017-02-16T17:08:09.524+0800 E QUERY [thread1] Error: listDatabases failed:{
"ok" : 0,
"errmsg" : "not master and slaveOk=false",
"code" : 13435,
"codeName" : "NotMasterNoSlaveOk"
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:62:1
shellHelper.show@src/mongo/shell/utils.js:755:19
shellHelper@src/mongo/shell/utils.js:645:15
@(shellhelp2):1:1
Myrepl:SECONDARY> rs.slaveOk() #执行此命令,之后查询就不报错了!
Myrepl:SECONDARY> show dbs
admin 0.000GB
local 0.000GB
testdb 0.000GB
Myrepl:SECONDARY> use testd
switched to db testdb
Myrepl:SECONDARY> db.testdb.findOne() #查询数据,可以看到在从服务器上已经有数据了
{
"_id" : ObjectId("58a56b7404b33bc093a90321"),
"name" : "repl",
"time" : "170216"
}
注意:通过上面的命令只能临时查询,下次再通过mongo命令进入后查询仍会报错,所以可以修改文件
#vi ~/.mongorc.js //写入下面这行
rs.slaveOk();
然后重启mongod进程!
我这里是root用户,所以在/root/.mongorc.js中添加即可!
4、模拟主服务器宕机,查看从服务器转变为主
首先在主服务器查看三台服务器的权重,如下:
Myrepl:PRIMARY> rs.config()
{
"_id" : "Myrepl",
"version" : 1,
"protocolVersion" : NumberLong(1),
"members" : [
{
"_id" : 0,
"host" : "10.0.18.144:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1, #优先级为1
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 1,
"host" : "10.0.18.149:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1, #优先级为1
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 2,
"host" : "10.0.18.150:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1, #优先级为1
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
}
],
"settings" : {
"chainingAllowed" : true,
"heartbeatIntervalMillis" : 2000,
"heartbeatTimeoutSecs" : 10,
"electionTimeoutMillis" : 10000,
"catchUpTimeoutMillis" : 2000,
"getLastErrorModes" : {
},
"getLastErrorDefaults" : {
"w" : 1,
"wtimeout" : 0
},
"replicaSetId" : ObjectId("58a568d2b205e55e0e0682d1")
}
}
注意:默认所有的机器权重(优先级)都为1,如果任何一个权重设置为比其他的高,则该台机器立马会切换为primary角色,所以要我们预设三台机器的权重
设置权重
预设主(18.144)权重为3、从(18.149)权重为2、从(18.150)权重为1(默认值可不用重新赋值)。
在主18.144上执行下面命令:
Myrepl:PRIMARY> cfg=rs.config() #重新赋值
{
"_id" : "Myrepl",
"version" : 1,
"protocolVersion" : NumberLong(1),
"members" : [
{
"_id" : 0,
"host" : "10.0.18.144:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 1,
"host" : "10.0.18.149:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 2,
"host" : "10.0.18.150: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" : 2000,
"getLastErrorModes" : {
},
"getLastErrorDefaults" : {
"w" : 1,
"wtimeout" : 0
},
"replicaSetId" : ObjectId("58a568d2b205e55e0e0682d1")
}
}
Myrepl:PRIMARY> cfg.members[0].priority = 3
3
Myrepl:PRIMARY> cfg.members[1].priority = 2
2
Myrepl:PRIMARY> rs.reconfig(cfg) #重新加载配置
{ "ok" : 1 }
Myrepl:PRIMARY> rs.config() #重新查看权重是否已经更改
{
"_id" : "Myrepl",
"version" : 2,
"protocolVersion" : NumberLong(1),
"members" : [
{
"_id" : 0,
"host" : "10.0.18.144:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 3, #变为了3
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 1,
"host" : "10.0.18.149:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 2, #变为了2
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 2,
"host" : "10.0.18.150:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1, #保持原来的1
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
}
],
"settings" : {
"chainingAllowed" : true,
"heartbeatIntervalMillis" : 2000,
"heartbeatTimeoutSecs" : 10,
"electionTimeoutMillis" : 10000,
"catchUpTimeoutMillis" : 2000,
"getLastErrorModes" : {
},
"getLastErrorDefaults" : {
"w" : 1,
"wtimeout" : 0
},
"replicaSetId" : ObjectId("58a568d2b205e55e0e0682d1")
}
}
5、停掉主(10.0.18.144)服务器的mongod进程
#killall mongod
然后在从服务器10.0.18.149上敲几下回车,从的角色立马由SECONDARY变为PRIMARY,如下:
Myrepl:SECONDARY>
Myrepl:SECONDARY>
Myrepl:SECONDARY>
Myrepl:PRIMARY>
Myrepl:PRIMARY>
Myrepl:PRIMARY> rs.status() #查看状态
{
"set" : "Myrepl",
"date" : ISODate("2017-02-16T10:12:40.419Z"),
"myState" : 1,
"term" : NumberLong(2),
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(1487239953, 1),
"t" : NumberLong(2)
},
"appliedOpTime" : {
"ts" : Timestamp(1487239953, 1),
"t" : NumberLong(2)
},
"durableOpTime" : {
"ts" : Timestamp(1487239953, 1),
"t" : NumberLong(2)
}
},
"members" : [
{
"_id" : 0,
"name" : "10.0.18.144:27017",
"health" : 0, #原来的主服务器health为0
"state" : 8,
"stateStr" : "(not reachable/healthy)", #而且是不可达的状态
"uptime" : 0,
"optime" : {
"ts" : Timestamp(0, 0),
"t" : NumberLong(-1)
},
"optimeDurable" : {
"ts" : Timestamp(0, 0),
"t" : NumberLong(-1)
},
"optimeDate" : ISODate("1970-01-01T00:00:00Z"),
"optimeDurableDate" : ISODate("1970-01-01T00:00:00Z"),
"lastHeartbeat" : ISODate("2017-02-16T10:12:39.422Z"),
"lastHeartbeatRecv" : ISODate("2017-02-16T10:10:43.056Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "Connection refused",
"configVersion" : -1
},
{
"_id" : 1,
"name" : "10.0.18.149:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY", #原来的从服务器因为优先级高,变成了主
"uptime" : 3446,
"optime" : {
"ts" : Timestamp(1487239953, 1),
"t" : NumberLong(2)
},
"optimeDate" : ISODate("2017-02-16T10:12:33Z"),
"infoMessage" : "could not find member to sync from",
"electionTime" : Timestamp(1487239853, 1),
"electionDate" : ISODate("2017-02-16T10:10:53Z"),
"configVersion" : 2,
"self" : true
},
{
"_id" : 2,
"name" : "10.0.18.150:27017",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 3445,
"optime" : {
"ts" : Timestamp(1487239953, 1),
"t" : NumberLong(2)
},
"optimeDurable" : {
"ts" : Timestamp(1487239953, 1),
"t" : NumberLong(2)
},
"optimeDate" : ISODate("2017-02-16T10:12:33Z"),
"optimeDurableDate" : ISODate("2017-02-16T10:12:33Z"),
"lastHeartbeat" : ISODate("2017-02-16T10:12:39.357Z"),
"lastHeartbeatRecv" : ISODate("2017-02-16T10:12:39.583Z"),
"pingMs" : NumberLong(0),
"syncingTo" : "10.0.18.149:27017",
"configVersion" : 2
}
],
"ok" : 1
}
注意:由上面可发现原来的主(18.144)已处于不健康状态(失连),而原来权重高的从(18.149)的角色变为PRIMARY,
权重低的从角色不变。不过要想让用户识别新主,还需手动指定读库的目标server!
6、原主恢复,新主写入的数据是否同步
在10.0.18.149这台新主服务器操作:
#mongo --host 10.0.18.149
MongoDB shell version v3.4.2
connecting to: mongodb://10.0.18.149:27017/
MongoDB server version: 3.4.2
在此服务器建库、建集合、插入数据
Myrepl:PRIMARY> show dbs;
admin 0.000GB
local 0.000GB
testdb 0.000GB
Myrepl:PRIMARY> use testdb2
switched to db testdb2
Myrepl:PRIMARY> db
testdb2
Myrepl:PRIMARY> db.createCollection('test2')
{ "ok" : 1 }
Myrepl:PRIMARY> show dbs
admin 0.000GB
local 0.000GB
testdb 0.000GB
testdb2 0.000GB
Myrepl:PRIMARY> db.testdb2.insert({"name":"repl2","time":"17021618"})db.testdb2.insert({"name":"repl2","time":"17021618"})
WriteResult({ "nInserted" : 1 })
Myrepl:PRIMARY> db.testdb2.findOne()
{
"_id" : ObjectId("58a57cd471c4e5a43bfa11fa"),
"name" : "repl2",
"time" : "17021618"
}
在第二台从服务器10.0.18.150查看数据
#mongo --host 10.0.18.150
MongoDB shell version v3.4.2
connecting to: mongodb://10.0.18.150:27017/
MongoDB server version: 3.4.2
Myrepl:SECONDARY> show dbs;
2017-02-16T18:21:23.860+0800 E QUERY [thread1] Error: listDatabases failed:{
"ok" : 0,
"errmsg" : "not master and slaveOk=false",
"code" : 13435,
"codeName" : "NotMasterNoSlaveOk"
} :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:62:1
shellHelper.show@src/mongo/shell/utils.js:755:19
shellHelper@src/mongo/shell/utils.js:645:15
@(shellhelp2):1:1
Myrepl:SECONDARY> rs.slaveOk()
Myrepl:SECONDARY> show dbs
admin 0.000GB
local 0.000GB
testdb 0.000GB
testdb2 0.000GB
也可以看到第二台从服务器已经从新主服务器复制了数据!
然后将原来的主服务器10.0.18.144的mongod进程启动,在新主服务器10.0.18.149回车查看如下:
Myrepl:PRIMARY>
2017-02-16T18:24:06.037+0800 I NETWORK [thread1] trying reconnect to 10.0.18.149:27017 (10.0.18.149) failed
2017-02-16T18:24:06.039+0800 I NETWORK [thread1] reconnect 10.0.18.149:27017 (10.0.18.149) ok
Myrepl:SECONDARY>
Myrepl:SECONDARY>
可以看到状态由原来的Myrepl:PRIMARY变为了Myrepl:SECONDARY
最后登录原主服务器查看数据是否存在
#mongo --host 10.0.18.144
MongoDB shell version v3.4.2
connecting to: mongodb://10.0.18.144:27017/
MongoDB server version: 3.4.2
Myrepl:PRIMARY> show dbs #可以看到testdb2库已经存在了
admin 0.000GB
local 0.000GB
testdb 0.000GB
testdb2 0.000GB
Myrepl:PRIMARY> use testdb2
switched to db testdb2
Myrepl:PRIMARY> db.testdb2.findOne() #数据也可以查看到
{
"_id" : ObjectId("58a57cd471c4e5a43bfa11fa"),
"name" : "repl2",
"time" : "17021618"
}
|
|