mongoDB的複製很是容易配置,其實現有兩種方式,一種是主從複製,一種是複製集,前者的好處是容易配置,可是若是主服務器宕掉了,整個系統就崩潰了,後者的好處是若是主服務器宕掉了,其餘服務器會經過投票選擇一個主服務器,所謂的主從服務器的區別在於,主服務器是能夠寫入的,從服務器默認連查詢都不支持,除非設置了slaveOK。mongodb
一、主從複製shell
1)環境服務器
角色 | 數據位置 | 端口 |
主服務器 | d:\mongodb_data\db1 | 27017 |
從服務器 | d:\mongodb_data\db2 | 27018 |
從服務器 | d:\mongodb_data\db3 | 27019 |
2)啓動(將對應數據位置的目錄清空)網絡
D:\mongodb_data>mongod --dbpath d:\mongodb_data\db1 --port=27017 --master spa
D:\mongodb_data>mongod --dbpath=d:\mongodb_data\db2 --port 27018 --slave --source 192.168.1.223:27017日誌
這裏的參數很容易理解,--master 表明主服務器, --slave 表明從服務器, --source 表明複製來源code
3)主服務器 server
D:\mongodb_data>mongo 192.168.1.223:27017
MongoDB shell version: 3.0.6
connecting to: 192.168.1.223:27017/test
> for(var i=0;i<10000;i++){
... db.students.insert({name:'ss'+i,code:'a'+i,id:i});
... }
WriteResult({ "nInserted" : 1 })
> db.students.count()
10000blog
4)從服務器 ci
D:\mongodb_data>mongo 192.168.1.223:27018
MongoDB shell version: 3.0.6
connecting to: 192.168.1.223:27018/test
> db.students.count()
10000
能夠看出複製成功了
5)增長一個從服務器,但不指定來源
D:\mongodb_data>mongod --dbpath d:\mongodb_data\db3 --port 27019 --slave
能夠在日誌中看出提示沒有指定複製來源
D:\mongodb_data>mongo 192.168.1.223:27019
MongoDB shell version: 3.0.6
connecting to: 192.168.1.223:27019/test
> db.students.count()
0
> use local
switched to db local
> db.sources.insert({host:'192.168.1.223:27017'});
WriteResult({ "nInserted" : 1 })
> use test
switched to db test
> db.students.count()
10000
能夠看出加入複製源以後,很快就同步過來了
這種複製方式很是簡單,可是不夠健壯,若是關掉主服務器,從服務器會收到以下信息
2015-09-30T17:13:39.073+0800 W NETWORK [replslave] Failed to connect to 192.168.1.223:27017, reason: errno:10061 因爲目標計算機積極拒絕,沒法鏈接。
2015-09-30T17:13:39.074+0800 I REPL [replslave] repl: couldn't connect to server 192.168.1.223:27017 (192.168.1.223), connection attempt failed
二、複製集
1)環境
角色 | 數據位置 | 端口 |
服務器1 | d:\mongodb_data\db1 | 27017 |
服務器2 | d:\mongodb_data\db2 | 27018 |
服務器3 | d:\mongodb_data\db3 | 27019 |
仲裁服務器 | d:\mongodb_data\db4 | 27020 |
2)啓動服務器(複製集的名稱爲testset,清除db1,db2,db3目錄)
D:\mongodb_data>mongod --dbpath db1 --port 27017 --replSet testset
D:\mongodb_data>mongod --dbpath db2 --port 27018 --replSet testset
D:\mongodb_data>mongod --dbpath db3 --port 27019 --replSet testset
3)鏈接和配置
D:\mongodb_data>mongo 192.168.1.223:27017 MongoDB shell version: 3.0.6 connecting to: 192.168.1.223:27017/test
> rs.initiate() { "info2" : "no configuration explicitly specified -- making one", "me" : "DESKTOP-3B9N9SB:27017", "ok" : 1 } testset:SECONDARY> rs.status() { "set" : "testset", "date" : ISODate("2015-09-30T09:25:42.449Z"), "myState" : 1, "members" : [ { "_id" : 0, "name" : "DESKTOP-3B9N9SB:27017", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 162, "optime" : Timestamp(1443605129, 1), "optimeDate" : ISODate("2015-09-30T09:25:29Z"), "electionTime" : Timestamp(1443605129, 2), "electionDate" : ISODate("2015-09-30T09:25:29Z"), "configVersion" : 1, "self" : true } ], "ok" : 1 } testset:PRIMARY> rs.add('192.168.1.223:27018'); { "ok" : 1 } testset:PRIMARY> rs.add('192.168.1.223:27019'); { "ok" : 1 } testset:PRIMARY> rs.status() { "set" : "testset", "date" : ISODate("2015-09-30T09:26:12.584Z"), "myState" : 1, "members" : [ { "_id" : 0, "name" : "DESKTOP-3B9N9SB:27017", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 192, "optime" : Timestamp(1443605169, 1), "optimeDate" : ISODate("2015-09-30T09:26:09Z"), "electionTime" : Timestamp(1443605129, 2), "electionDate" : ISODate("2015-09-30T09:25:29Z"), "configVersion" : 3, "self" : true }, { "_id" : 1, "name" : "192.168.1.223:27018", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 6, "optime" : Timestamp(1443605169, 1), "optimeDate" : ISODate("2015-09-30T09:26:09Z"), "lastHeartbeat" : ISODate("2015-09-30T09:26:11.742Z"), "lastHeartbeatRecv" : ISODate("2015-09-30T09:26:12.447Z" ), "pingMs" : 0, "syncingTo" : "DESKTOP-3B9N9SB:27017", "configVersion" : 3 }, { "_id" : 2, "name" : "192.168.1.223:27019", "health" : 1, "state" : 5, "stateStr" : "STARTUP2", "uptime" : 2, "optime" : Timestamp(0, 0), "optimeDate" : ISODate("1970-01-01T00:00:00Z"), "lastHeartbeat" : ISODate("2015-09-30T09:26:11.755Z"), "lastHeartbeatRecv" : ISODate("2015-09-30T09:26:11.782Z" ), "pingMs" : 12, "configVersion" : 3 } ], "ok" : 1 }
須要注意的是,首先要運行rs.initiate(),而後要運行rs.add()增長複製服務器,用rs.status()能夠看到狀態,能夠看出27017是Primary,其餘都是Secondary
3)驗證
在27017插入
testset:PRIMARY> for(var i=0;i<10000;i++){ ... db.students.insert({name:'ss'+i,code:'aa'+i,id:i}); ... } WriteResult({ "nInserted" : 1 }) testset:PRIMARY> db.students.count(); 10000
D:\mongodb_data>mongo 192.168.1.223:27018 MongoDB shell version: 3.0.6 connecting to: 192.168.1.223:27018/test
testset:SECONDARY> db.students.count() 2015-09-30T17:31:11.883+0800 E QUERY Error: count failed: { "note" : "from ex ecCommand", "ok" : 0, "errmsg" : "not master" } at Error (<anonymous>) at DBQuery.count (src/mongo/shell/query.js:326:11)
at DBCollection.count (src/mongo/shell/collection.js:1046:27)
at (shell):1:13 at src/mongo/shell/query.js:326
testset:SECONDARY> rs.slaveOk() testset:SECONDARY> db.students.count() 10000
D:\mongodb_data>mongo 192.168.1.223:27019 MongoDB shell version: 3.0.6 connecting to: 192.168.1.223:27019/test
testset:SECONDARY> rs.slaveOk() testset:SECONDARY> db.students.count() 10000
此時能夠看到複製已經成功了,可是從服務器默認是不能查詢的,須要設置slaveOk,才能夠查詢,大部分的驅動程序都支持這個設置,而且在鏈接集羣的時候,驅動程序會自動切換,找到合適的服務器,若是某一個服務器宕機了,就能夠無縫切換到其餘服務器。
在這種集羣環境下,若是主服務器宕掉了,其餘的幾個服務器會通過投票,選出一個服務器做爲主服務器,因此集羣是無縫切換的,只有在投票期間是不對外服務的,不過這個時間很短,若是網絡較好、且服務器很少,能夠在幾秒內切換完畢。