MongoDB的復(fù)制主要分2種,一種是Master-Salve(主從復(fù)制),一種是副本集(replica sets),MongoDB4.0之后就不支持主從復(fù)制了,官方原話
MongoDB 4.0 removes support for the deprecated master-slave replication. Before you can upgrade to MongoDB 4.0, if your deployment uses master-slave replication, you must upgrade to a replica set.
MongoDB 4.0刪除了對主從復(fù)制的支持。在升級到MongoDB 4.0之前,如果部署使用主從復(fù)制,則必須升級到副本集.本文只講解副本集的部署步驟。副本集相比較主從復(fù)制而言有2點(diǎn)區(qū)別:
- 該集群沒有特定的主數(shù)據(jù)庫。
- 如果哪個(gè)主數(shù)據(jù)庫宕機(jī)了,集群中就會(huì)推選出一個(gè)從屬數(shù)據(jù)庫作為主數(shù)據(jù)庫頂上,這就具備了自動(dòng)故障恢復(fù)功能,很牛X的啊。
角色說明:
1.主庫
理論上所有副本集中的數(shù)據(jù)庫都能讀取數(shù)據(jù),但是系統(tǒng)會(huì)默認(rèn)讓主庫來完成讀取數(shù)據(jù)的功能
2.輔助副本
主服務(wù)器是副本集中唯一接收寫操作的成員。MongoDB在主服務(wù)器上應(yīng)用寫操作,然后在主服務(wù)器的oplog上記錄操作。輔助成員復(fù)制此日志并將操作應(yīng)用于其數(shù)據(jù)集。
3.仲裁者
在主庫宕機(jī)后重新投票選舉出新的主庫,它自己不能是主庫也不能是輔助副本
副本集配置
1.創(chuàng)建每個(gè)庫的配置文件,日志文件和數(shù)據(jù)存檔的目錄,我本機(jī)選擇的是 /Data/MongoReplSet/下,MongoReplSet也是我自建的
MongoReplSet下的目錄結(jié)構(gòu)
├── conf
│ ├── db1.conf
│ ├── db2.conf
│ └── db3.conf
├── dbs
│ ├── db1
│ ├── db2
│ └── db3
└── logs
├── db1.log
├── db2.log
└── db3.log
conf下的配置內(nèi)容,其中replSet的值是這個(gè)副本集的名稱
db1.conf
? dbpath=/Data/MongoReplSet/dbs/db1
? logpath=/Data/MongoReplSet/logs/db1.log
? logappend=true
? noprealloc=true
? port=27011
? fork=true
? replSet=testdb2.conf
? dbpath=/Data/MongoReplSet/dbs/db2
? logpath=/Data/MongoReplSet/logs/db2.log
? logappend=true
? noprealloc=true
? port=27012
? fork=true
? replSet=testdb3.conf
? dbpath=/Data/MongoReplSet/dbs/db3
? logpath=/Data/MongoReplSet/logs/db3.log
? logappend=true
? noprealloc=true
? port=27013
? fork=true
? replSet=test
2.進(jìn)入3個(gè)實(shí)例中的任何一個(gè),初始化副本集
mongo --port 27011
use admin
config={
_id:'test',
members:[
{_id:1, host:'localhost:27011',priority:2},
{_id:2, host:'localhost:27012',priority:1},
{_id:3, host:'localhost:27013',arbiterOnly:true}
]
}
rs.initiate(config)
_id:'test'表示副本集名稱,與前面conf配置文件中的replSet參數(shù)配置的名稱要一致。
priority:2表示優(yōu)先級,優(yōu)先級越高,副本集初始化時(shí)會(huì)選舉為主庫。arbiterOnly:true表示該實(shí)例為仲裁節(jié)點(diǎn),不存儲(chǔ)數(shù)據(jù),只參與投票。
3.rs.status()查看副本集狀態(tài)
test:SECONDARY> rs.status()
{
"set" : "test",
"date" : ISODate("2019-03-05T05:44:28.581Z"),
"myState" : 2,
"term" : NumberLong(0),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"heartbeatIntervalMillis" : NumberLong(2000),
"optimes" : {
"lastCommittedOpTime" : {
"ts" : Timestamp(0, 0),
"t" : NumberLong(-1)
},
"appliedOpTime" : {
"ts" : Timestamp(1551764659, 1),
"t" : NumberLong(-1)
},
"durableOpTime" : {
"ts" : Timestamp(1551764659, 1),
"t" : NumberLong(-1)
}
},
"lastStableCheckpointTimestamp" : Timestamp(0, 0),
"members" : [
{
"_id" : 1,
"name" : "localhost:27011",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 108,
"optime" : {
"ts" : Timestamp(1551764659, 1),
"t" : NumberLong(-1)
},
"optimeDate" : ISODate("2019-03-05T05:44:19Z"),
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "could not find member to sync from",
"configVersion" : 1,
"self" : true,
"lastHeartbeatMessage" : ""
},
{
"_id" : 2,
"name" : "localhost:27012",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 8,
"optime" : {
"ts" : Timestamp(1551764659, 1),
"t" : NumberLong(-1)
},
"optimeDurable" : {
"ts" : Timestamp(1551764659, 1),
"t" : NumberLong(-1)
},
"optimeDate" : ISODate("2019-03-05T05:44:19Z"),
"optimeDurableDate" : ISODate("2019-03-05T05:44:19Z"),
"lastHeartbeat" : ISODate("2019-03-05T05:44:28.245Z"),
"lastHeartbeatRecv" : ISODate("2019-03-05T05:44:28.124Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"configVersion" : 1
},
{
"_id" : 3,
"name" : "localhost:27013",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 8,
"lastHeartbeat" : ISODate("2019-03-05T05:44:28.245Z"),
"lastHeartbeatRecv" : ISODate("2019-03-05T05:44:27.654Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "",
"syncingTo" : "",
"syncSourceHost" : "",
"syncSourceId" : -1,
"infoMessage" : "",
"configVersion" : 1
}
],
"ok" : 1,
"operationTime" : Timestamp(1551764659, 1),
"$clusterTime" : {
"clusterTime" : Timestamp(1551764659, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
}
members下面就是整個(gè)副片集的成員,其中 27011端口號下面的 infoMessage:'could not find member to sync from',表示它沒有可以同步的數(shù)據(jù)集,因?yàn)樗侵鲙欤回?fù)責(zé)寫入
4.主庫添加測試數(shù)據(jù)
test:PRIMARY> use test
switched to db test
test:PRIMARY> db.person.insertMany([{"name":"tom", "age": 20}, {"name":"jack", "age":21}, {"name":"luna", "age":18}])
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("5c7e13b79d270105c2390fcd"),
ObjectId("5c7e13b79d270105c2390fce"),
ObjectId("5c7e13b79d270105c2390fcf")
]
}
進(jìn)副庫檢查
mongo --port 27012
test:SECONDARY> show dbs
2019-03-05T14:14:44.483+0800 E QUERY [js] Error: listDatabases failed:{
"operationTime" : Timestamp(1551766483, 1),
"ok" : 0,
"errmsg" : "not master and slaveOk=false",
"code" : 13435,
"codeName" : "NotMasterNoSlaveOk",
"$clusterTime" : {
"clusterTime" : Timestamp(1551766483, 1),
"signature" : {
"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
"keyId" : NumberLong(0)
}
}
} :
發(fā)現(xiàn)沒有權(quán)限查看,臨時(shí)解決方案 執(zhí)行 rs.slaveOk()
test:SECONDARY> rs.slaveOk()
test:SECONDARY> show collections
person
test:SECONDARY> db.person.find()
{ "_id" : ObjectId("5c7e652ecf158632e56497cb"), "name" : "jack", "age" : 21 }
{ "_id" : ObjectId("5c7e652ecf158632e56497cc"), "name" : "luna", "age" : 18 }
{ "_id" : ObjectId("5c7e652ecf158632e56497ca"), "name" : "tom", "age" : 20 }