為什么使用MongogDB復制集技術?
mysql中:一主一從,一主多從結構存在的問題 1、 fileover(故障轉移) a) 選主投票 b) 切換 2、 是否對就用透明化 3、 數據補償的問題 a) 兩階段數據補償 4、 解決方法 mysql中使用MHA+VIP + binlogserver
mongodb通過復制集技術解決以上所有問題,不需要第三方軟件,自已原生支持
MongoDB復制集簡介
一組Mongodb復制集,就是一組mongod進程,這些進程維護同一個數據集合。復制集提供了數據冗余和高等級的可靠性,這是生產部署的基礎。
保證數據在生產部署時的冗余和可靠性,通過在不同的機器上保存副本來保證數據的不會因為單點損壞而丟失。能夠隨時應對數據丟失、機器損壞帶來的風險,牛逼到不行。換一句話來說,還能提高讀取能力,用戶的讀取服務器和寫入服務器在不同的地方,而且,由不同的服務器為不同的用戶提供服務,提高整個系統的負載,簡直就是雲存儲的翻版...一組復制集就是一組mongod實例掌管同一個數據集,實例可以在不同的機器上面。實例中包含一個主導,接受客戶端所有的寫入操作,其他都是副本實例,從主服務器上獲得數據並保持同步。
主服務器很重要,包含了所有的改變操作(寫)的日志。但是副本服務器集群包含有所有的主服務器數據,因此當主服務器掛掉了,就會在副本服務器上重新選取一個成為主服務器。每個復制集還有一個仲裁者,仲裁者不存儲數據,只是負責通過心跳包來確
認集群中集合的數量,並在主服務器選舉的時候作為仲裁決定結果。
復制的基本架構
一個包含3個mongod的復制集架構如下所示
如果主服務器失效,會變成:
如果加上可選的仲裁者:
如果主服務器失效:
復制集技術實現
搭建三節點MongoDB復制集
#創建多mongodb多實例
mkdir -p /mongodb/28017/conf /mongodb/28017/data /mongodb/28017/log mkdir -p /mongodb/28018/conf /mongodb/28018/data /mongodb/28018/log mkdir -p /mongodb/28019/conf /mongodb/28019/data /mongodb/28019/log mkdir -p /mongodb/28020/conf /mongodb/28020/data /mongodb/28020/log #創建mongodb多 vim /mongodb/28017/conf/mongod.conf systemLog: destination: file path: /mongodb/28017/log/mongodb.log logAppend: true storage: journal: enabled: true dbPath: /mongodb/28017/data directoryPerDB: true #engine: wiredTiger wiredTiger: engineConfig: cacheSizeGB: 1 directoryForIndexes: true collectionConfig: blockCompressor: zlib indexConfig: prefixCompression: true processManagement: fork: true net: port: 28017 replication: oplogSizeMB: 2048 replSetName: my_repl \cp /mongodb/28017/conf/mongod.conf /mongodb/28018/conf/ \cp /mongodb/28017/conf/mongod.conf /mongodb/28019/conf/ \cp /mongodb/28017/conf/mongod.conf /mongodb/28020/conf/ sed 's#28017#28018#g' /mongodb/28018/conf/mongod.conf -i sed 's#28017#28019#g' /mongodb/28019/conf/mongod.conf -i sed 's#28017#28020#g' /mongodb/28020/conf/mongod.conf -i chown -R mongod:mongod /mongodb/ su - mongod mongod -f /mongodb/28017/conf/mongod.conf mongod -f /mongodb/28018/conf/mongod.conf mongod -f /mongodb/28019/conf/mongod.conf mongod -f /mongodb/28020/conf/mongod.conf
登錄
mongo --port=28017 use admin config = {_id: 'my_repl', members: [ {_id: 0, host: '10.0.0.134:28017'}, {_id: 1, host: '10.0.0.134:28018'}, {_id: 2, host: '10.0.0.134:28019'}] } rs.initiate(config) use test; db.movies.insert([ { "title" : "Jaws", "year" : 1975, "imdb_rating" : 8.1 },{ "title" : "Batman", "year" : 1989, "imdb_rating" : 7.6 }, ] );
#復制集狀態查詢 在哪個節點都可以看
[mongod@mongo ~]$ mongo --port=28017 MongoDB shell version: 3.2.8 connecting to: 127.0.0.1:28017/test my_repl:PRIMARY> rs.status(); { "set" : "my_repl", "date" : ISODate("2018-01-04T09:06:52.951Z"), "myState" : 1, "term" : NumberLong(1), "heartbeatIntervalMillis" : NumberLong(2000), "members" : [ { "_id" : 0, "name" : "10.0.0.134:28017", #ip port "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "PRIMARY" 主節點 "uptime" : 772, "optime" : { "ts" : Timestamp(1515056188, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2018-01-04T08:56:28Z"), "electionTime" : Timestamp(1515056187, 1), "electionDate" : ISODate("2018-01-04T08:56:27Z"), "configVersion" : 1, "self" : true }, { "_id" : 1, "name" : "10.0.0.134:28018", #ip port "health" : 1, "state" : 2, "stateStr" : "SECONDARY", #從節點 "uptime" : 635, "optime" : { "ts" : Timestamp(1515056188, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2018-01-04T08:56:28Z"), "lastHeartbeat" : ISODate("2018-01-04T09:06:52.289Z"), "lastHeartbeatRecv" : ISODate("2018-01-04T09:06:51.722Z"), "pingMs" : NumberLong(0), "syncingTo" : "10.0.0.134:28017", "configVersion" : 1 }, { "_id" : 2, "name" : "10.0.0.134:28019", #ip port "health" : 1, "state" : 2, "stateStr" : "SECONDARY", #從節點 "uptime" : 635, "optime" : { "ts" : Timestamp(1515056188, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2018-01-04T08:56:28Z"), "lastHeartbeat" : ISODate("2018-01-04T09:06:52.289Z"), "lastHeartbeatRecv" : ISODate("2018-01-04T09:06:51.601Z"), "pingMs" : NumberLong(0), "syncingTo" : "10.0.0.134:28017", "configVersion" : 1 } ], "ok" : 1 }
#查看當前是否為主節點
#主節點檢測 my_repl:PRIMARY> rs.isMaster(); { "hosts" : [ "10.0.0.134:28017", "10.0.0.134:28018", "10.0.0.134:28019" ], "setName" : "my_repl", "setVersion" : 1, "ismaster" : true, #主節點 "secondary" : false, "primary" : "10.0.0.134:28017", "me" : "10.0.0.134:28017", "electionId" : ObjectId("7fffffff0000000000000001"), "maxBsonObjectSize" : 16777216, "maxMessageSizeBytes" : 48000000, "maxWriteBatchSize" : 1000, "localTime" : ISODate("2018-01-04T09:11:15.204Z"), "maxWireVersion" : 4, "minWireVersion" : 0, "ok" : 1 } #從節點檢測 [mongod@mongo ~]$ mongo --port=28018 MongoDB shell version: 3.2.8 connecting to: 127.0.0.1:28018/test my_repl:SECONDARY> rs.isMaster() { "hosts" : [ "10.0.0.134:28017", "10.0.0.134:28018", "10.0.0.134:28019" ], "setName" : "my_repl", "setVersion" : 1, "ismaster" : false, "secondary" : true, #從節點 "primary" : "10.0.0.134:28017", "me" : "10.0.0.134:28018", "maxBsonObjectSize" : 16777216, "maxMessageSizeBytes" : 48000000, "maxWriteBatchSize" : 1000, "localTime" : ISODate("2018-01-04T09:11:40.092Z"), "maxWireVersion" : 4, "minWireVersion" : 0, "ok" : 1 }
#在主節點上添加節點
my_repl:PRIMARY> rs.add ("10.0.0.134:28020") #添加從節點 { "ok" : 1 } my_repl:PRIMARY> rs.status() { "set" : "my_repl", "date" : ISODate("2018-01-04T09:16:33.144Z"), "myState" : 1, "term" : NumberLong(1), "heartbeatIntervalMillis" : NumberLong(2000), "members" : [ { "_id" : 0, "name" : "10.0.0.134:28017", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 1353, "optime" : { "ts" : Timestamp(1515057249, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2018-01-04T09:14:09Z"), "electionTime" : Timestamp(1515056187, 1), "electionDate" : ISODate("2018-01-04T08:56:27Z"), "configVersion" : 2, "self" : true }, { "_id" : 1, "name" : "10.0.0.134:28018", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 1216, "optime" : { "ts" : Timestamp(1515057249, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2018-01-04T09:14:09Z"), "lastHeartbeat" : ISODate("2018-01-04T09:16:31.632Z"), "lastHeartbeatRecv" : ISODate("2018-01-04T09:16:31.693Z"), "pingMs" : NumberLong(0), "syncingTo" : "10.0.0.134:28017", "configVersion" : 2 }, { "_id" : 2, "name" : "10.0.0.134:28019", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 1216, "optime" : { "ts" : Timestamp(1515057249, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2018-01-04T09:14:09Z"), "lastHeartbeat" : ISODate("2018-01-04T09:16:31.632Z"), "lastHeartbeatRecv" : ISODate("2018-01-04T09:16:31.693Z"), "pingMs" : NumberLong(0), "syncingTo" : "10.0.0.134:28017", "configVersion" : 2 }, { "_id" : 3, "name" : "10.0.0.134:28020", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", #從節點10.0.0.134:28020 "uptime" : 143, "optime" : { "ts" : Timestamp(1515057249, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2018-01-04T09:14:09Z"), "lastHeartbeat" : ISODate("2018-01-04T09:16:31.647Z"), "lastHeartbeatRecv" : ISODate("2018-01-04T09:16:30.645Z"), "pingMs" : NumberLong(0), "configVersion" : 2 } ], "ok" : 1 }
#刪除節點
my_repl:PRIMARY> rs.remove("10.0.0.134:28020") #刪除從節點 { "ok" : 1 } my_repl:PRIMARY> rs.status() { "set" : "my_repl", "date" : ISODate("2018-01-04T09:18:10.582Z"), "myState" : 1, "term" : NumberLong(1), "heartbeatIntervalMillis" : NumberLong(2000), "members" : [ { "_id" : 0, "name" : "10.0.0.134:28017", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 1450, "optime" : { "ts" : Timestamp(1515057484, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2018-01-04T09:18:04Z"), "electionTime" : Timestamp(1515056187, 1), "electionDate" : ISODate("2018-01-04T08:56:27Z"), "configVersion" : 3, "self" : true }, { "_id" : 1, "name" : "10.0.0.134:28018", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 1313, "optime" : { "ts" : Timestamp(1515057484, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2018-01-04T09:18:04Z"), "lastHeartbeat" : ISODate("2018-01-04T09:18:10.231Z"), "lastHeartbeatRecv" : ISODate("2018-01-04T09:18:10.241Z"), "pingMs" : NumberLong(0), "syncingTo" : "10.0.0.134:28017", "configVersion" : 3 }, { "_id" : 2, "name" : "10.0.0.134:28019", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 1313, "optime" : { "ts" : Timestamp(1515057484, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2018-01-04T09:18:04Z"), "lastHeartbeat" : ISODate("2018-01-04T09:18:10.231Z"), "lastHeartbeatRecv" : ISODate("2018-01-04T09:18:10.243Z"), "pingMs" : NumberLong(0), "syncingTo" : "10.0.0.134:28017", "configVersion" : 3 } ], "ok" : 1 }
#添加仲裁節點
my_repl:PRIMARY> rs.addArb("10.0.0.134:28020");#添加仲裁節點 { "ok" : 1 } my_repl:PRIMARY> rs.status(); { "set" : "my_repl", "date" : ISODate("2018-01-04T09:19:32.814Z"), "myState" : 1, "term" : NumberLong(1), "heartbeatIntervalMillis" : NumberLong(2000), "members" : [ { "_id" : 0, "name" : "10.0.0.134:28017", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 1532, "optime" : { "ts" : Timestamp(1515057570, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2018-01-04T09:19:30Z"), "electionTime" : Timestamp(1515056187, 1), "electionDate" : ISODate("2018-01-04T08:56:27Z"), "configVersion" : 6, "self" : true }, { "_id" : 1, "name" : "10.0.0.134:28018", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 1395, "optime" : { "ts" : Timestamp(1515057570, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2018-01-04T09:19:30Z"), "lastHeartbeat" : ISODate("2018-01-04T09:19:30.915Z"), "lastHeartbeatRecv" : ISODate("2018-01-04T09:19:30.926Z"), "pingMs" : NumberLong(0), "syncingTo" : "10.0.0.134:28017", "configVersion" : 5 }, { "_id" : 2, "name" : "10.0.0.134:28019", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 1395, "optime" : { "ts" : Timestamp(1515057534, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2018-01-04T09:18:54Z"), "lastHeartbeat" : ISODate("2018-01-04T09:19:30.902Z"), "lastHeartbeatRecv" : ISODate("2018-01-04T09:19:30.922Z"), "pingMs" : NumberLong(0), "syncingTo" : "10.0.0.134:28017", "configVersion" : 5 }, { "_id" : 4, "name" : "10.0.0.134:28020", "health" : 1, "state" : 7, "stateStr" : "ARBITER", #仲裁節點 "uptime" : 34, "lastHeartbeat" : ISODate("2018-01-04T09:19:30.903Z"), "lastHeartbeatRecv" : ISODate("2018-01-04T09:19:30.924Z"), "pingMs" : NumberLong(0), "syncingTo" : "10.0.0.134:28019", "configVersion" : 5 } ], "ok" : 1 }
#主、從、仲裁節點對比
#主節點操作 [mongod@mongo ~]$ mongo --port=28017 MongoDB shell version: 3.2.8 connecting to: 127.0.0.1:28017/test my_repl:PRIMARY> use test switched to db test my_repl:PRIMARY> db.anyux.insert([{"language":"C"},{"language":"C++"}]) #插入數據 BulkWriteResult({ "writeErrors" : [ ], "writeConcernErrors" : [ ], "nInserted" : 2, "nUpserted" : 0, "nMatched" : 0, "nModified" : 0, "nRemoved" : 0, "upserted" : [ ] }) my_repl:PRIMARY> db.anyux.find().pretty() #主節點顯示數據 { "_id" : ObjectId("5a4df337c702312dedac9176"), "language" : "C" } { "_id" : ObjectId("5a4df337c702312dedac9177"), "language" : "C++" } #從節點操作 MongoDB shell version: 3.2.8 connecting to: 127.0.0.1:28018/test my_repl:SECONDARY> use test my_repl:SECONDARY> rs.slaveOk(); my_repl:SECONDARY> db.anyux.find().pretty() #從節點顯示數據 { "_id" : ObjectId("5a4df337c702312dedac9176"), "language" : "C" } { "_id" : ObjectId("5a4df337c702312dedac9177"), "language" : "C++" } #仲裁節點 [mongod@mongo ~]$ mongo --port=28020 MongoDB shell version: 3.2.8 connecting to: 127.0.0.1:28020/test my_repl:ARBITER> rs.slaveOk(); my_repl:ARBITER> show dbs; local 0.000GB test 0.000GB my_repl:ARBITER> db.anyux.find().pretty(); #仲裁節點不會存儲數據 Error: error: { "ok" : 0, "errmsg" : "node is recovering", "code" : 13436 }