MongoDB複製集是一個帶有故障轉移的主從集羣。是從現有的主從模式演變而來,增長了自動故障轉移和節點成員自動恢復。MongoDB複製集模式中沒有固定的主結點,在啓動後,多個服務節點間將自動選舉產生一個主結點。該主結點被稱爲primary,一個或多個從結點被稱爲secondaries。primary結點基本上就是master結點,不一樣之處在於primary結點在不一樣時間多是不一樣的服務器。若是當前的主結點失效了,複製集中的其他結點將會試圖選出一個新的主結點。linux
MongoDB複製集模式的好處:mongodb
在一個MongoDB複製集集羣中,各個服務器有如下幾種狀態:shell
如上介紹所知,mongodb中的複製能夠在多臺服務器中同步數據。複製提供了冗餘和增長了數據的高可用性,防止單個節點易丟失數據的可能性,也能夠用來進行讀寫分離提升客戶端操做性能。複製集中各節點的mongodb實例有相同的數據集副本。主節點能夠接收客戶端全部寫操做記錄到日誌中,從庫複製主庫的操做日誌記錄應用到其數據庫中。一個客戶端只能有一個主節點,若是主節點不可用(10秒內沒法鏈接),複製集中將選一個成員節點做爲主節點。數據庫
MongoDB主備+仲裁的基本結構以下:vim
主節點(Primary)
在複製集中,主節點是惟一可以接收寫請求的節點。MongoDB在主節點進行寫操做,並將這些操做記錄到主節點的oplog中。而從節點將會從oplog複製到其本機,並將這些操做應用到本身的數據集上。(複製集最多隻能擁有一個主節點)
從節點(Secondaries)
從節點經過應用主節點傳來的數據變更操做來保持其數據集與主節點一致。從節點也能夠經過增長額外參數配置來對應特殊需求。例如,從節點能夠是non-voting或是priority 0.
仲裁節點(ARBITER)
仲裁節點即投票節點,其自己並不包含數據集,且也沒法晉升爲主節點。可是,旦當前的主節點不可用時,投票節點就會參與到新的主節點選舉的投票中。仲裁節點使用最小的資源而且不要求硬件設備。投票節點的存在使得複製集能夠以偶數個節點存在,而無需爲複製集再新增節點 不要將投票節點運行在複製集的主節點或從節點機器上。 投票節點與其餘 複製集節點的交流僅有:選舉過程當中的投票,心跳檢測和配置數據。這些交互都是不加密的。bash
心跳檢測
複製集成員每兩秒向複製集中其餘成員進行心跳檢測。若是某個節點在10秒內沒有返回,那麼它將被標記爲不可用。服務器
MongoDB副本集是有故障恢復功能的主從集羣,由一個primary節點和一個或多個secondary節點組成:
節點同步過程: Primary節點寫入數據,Secondary經過讀取Primary的oplog獲得複製信息,開始複製數據而且將複製信息寫入到本身的oplog。若是某個操做失敗,則備份節點中止從當前數據源複製數據。若是某個備份節點因爲某些緣由掛掉了,當從新啓動後,就會自動從oplog的最後一個操做開始同步,同步完成後,將信息寫入本身的oplog,因爲複製操做是先複製數據,複製完成後再寫入oplog,有可能相同的操做會同步兩份,不過MongoDB在設計之初就考慮到這個問題,將oplog的同一個操做執行屢次,與執行一次的效果是同樣的。app
通俗理解:當Primary節點完成數據操做後,Secondary會作出一系列的動做保證數據的同步:
- 檢查本身local庫的oplog.rs集合,找出最近的時間戳。
- 檢查Primary節點local庫oplog.rs集合,找出大於此時間戳的記錄。
- 將找到的記錄插入到本身的oplog.rs集合中,並執行這些操做。dom
副本集的同步和主從同步同樣,都是異步同步的過程,不一樣的是副本集有個自動故障轉移的功能。其原理是:slave端從primary端獲取日誌,而後在本身身上徹底順序的執行日誌所記錄的各類操做(該日誌是不記錄查詢操做的),這個日誌就是local數據 庫中的oplog.rs表,默認在64位機器上這個表是比較大的,佔磁盤大小的5%,oplog.rs的大小能夠在啓動參數中設 定:–oplogSize 1000,單位是M。異步
注意:在副本集的環境中,要是全部的Secondary都宕機了,只剩下Primary。最後Primary會變成Secondary,不能提供服務。
下面簡單介紹下MongoDB 副本集的部署過程:
1)服務器信息 sign-mongo01.wangshibo.cn 172.16.51.216 Primary sign-mongo02.wangshibo.cn 172.16.51.217 Secondary sign-mongo03.wangshibo.cn 172.16.51.218 Arbiter 三臺服務器均設置好主機名,關閉iptables及selinux(略) 2)在3臺服務器文件hosts文件中都添加如下3行: [root@sign-mongo01 ~]# cat /etc/hosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 172.16.51.216 sign-mongo01.wangshibo.cn 172.16.51.217 sign-mongo02.wangshibo.cn 172.16.51.218 sign-mongo03.wangshibo.cn 3)安裝部署mongodb(三臺機器都安裝) 下載地址:https://www.mongodb.org/dl/linux/x86_64-rhel62 [app@sign-mongo01 software]$ pwd /data/software [app@sign-mongo01 software]$ ls mongodb-linux-x86_64-rhel62-v3.2-latest.tgz [app@sign-mongo01 software]$ tar -zvxf mongodb-linux-x86_64-rhel62-v3.2-latest.tgz [app@sign-mongo01 software]$ mv mongodb-linux-x86_64-rhel62-3.2.17-34-g4c1bae566c /data/mongodb [app@sign-mongo01 software]$ cd /data/mongodb/ [app@sign-mongo01 mongodb]$ mkdir data [app@sign-mongo01 mongodb]$ mkdir log [app@sign-mongo01 mongodb]$ vim mongodb.conf pidfilepath=/data/mongodb/log/mongod.pid logpath=/data/mongodb/log/mongod.log dbpath=/data/mongodb logappend=true bind_ip=172.16.51.216 port=27017 fork=true replSet=rs0 備節點的mongodb.conf配置文件分別爲: [app@sign-mongo02 mongodb]$ vim mongodb.conf pidfilepath=/data/mongodb/log/mongod.pid logpath=/data/mongodb/log/mongod.log dbpath=/data/mongodb logappend=true bind_ip=172.16.51.217 port=27018 fork=true replSet=rs0 其中:replSet=rs0 #表示複製集名稱:rs0 啓動主備服務器的mongodb [app@sign-mongo01 ~]$ /data/mongodb/bin/mongod --config /data/mongodb/mongodb.conf about to fork child process, waiting until server is ready for connections. forked process: 7317 child process started successfully, parent exiting [app@sign-mongo01 mongodb]$ ps -ef|grep mongodb app 7317 1 0 21:38 ? 00:00:00 /data/mongodb/bin/mongod --config /data/mongodb/mongodb.conf app 7342 7254 0 21:38 pts/1 00:00:00 grep mongodb [app@sign-mongo01 mongodb]$ lsof -i:27017 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME mongod 7317 app 6u IPv4 27011 0t0 TCP sign-mongo01.wangshibo.cn:27017 (LISTEN) [app@sign-mongo02 mongodb]$ /data/mongodb/bin/mongod --config /data/mongodb/mongodb.conf about to fork child process, waiting until server is ready for connections. forked process: 9725 child process started successfully, parent exiting [app@sign-mongo02 mongodb]$ lsof -i:27018 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME mongod 9725 app 6u IPv4 27191 0t0 TCP sign-mongo02.wangshibo.cn:27018 (LISTEN) 設置mongodb的環變量 [root@sign-mongo01 src]# vim /etc/profile ...... export PATH=$PATH:/data/mongodb/bin [root@sign-mongo01 src]# source /etc/profile 登陸到mongodb中: [app@sign-mongo01 ~]$ mongo 172.16.51.216:27017 MongoDB shell version: 3.2.17-34-g4c1bae566c connecting to: 172.16.51.216:27017/test Welcome to the MongoDB shell. For interactive help, type "help". For more comprehensive documentation, see http://docs.mongodb.org/ Questions? Try the support group http://groups.google.com/group/mongodb-user Server has startup warnings: 2017-11-22T21:38:18.063+0800 I CONTROL [initandlisten] 2017-11-22T21:38:18.063+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'. 2017-11-22T21:38:18.063+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2017-11-22T21:38:18.063+0800 I CONTROL [initandlisten] 2017-11-22T21:38:18.063+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'. 2017-11-22T21:38:18.063+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2017-11-22T21:38:18.063+0800 I CONTROL [initandlisten] > 初始化複製集:(集合爲:"rs0" ;第一個成員爲:"sign-mongo01.wangshibo.cn:27017" > rs.initiate({_id: "rs0",members: [{ _id: 0 , host: "sign-mongo01.wangshibo.cn:27017" }]}) { "ok" : 1 } rs0:OTHER> //接着回車,顯示這個節點爲Primary主節點 rs0:PRIMARY> 接着添加另1個成員: rs0:PRIMARY> rs.add("sign-mongo02.wangshibo.cn:27018") { "ok" : 1 } 查當作員信息 (或者使用 db.isMaster() ) rs0:PRIMARY> rs.status() { "set" : "rs0", "date" : ISODate("2017-11-22T13:55:28.446Z"), "myState" : 1, "term" : NumberLong(1), "heartbeatIntervalMillis" : NumberLong(2000), "members" : [ { "_id" : 0, "name" : "sign-mongo01.wangshibo.cn:27017", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 1031, "optime" : { "ts" : Timestamp(1511358895, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2017-11-22T13:54:55Z"), "infoMessage" : "could not find member to sync from", "electionTime" : Timestamp(1511358843, 2), "electionDate" : ISODate("2017-11-22T13:54:03Z"), "configVersion" : 2, "self" : true }, { "_id" : 1, "name" : "sign-mongo02.wangshibo.cn:27018", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 32, "optime" : { "ts" : Timestamp(1511358895, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2017-11-22T13:54:55Z"), "lastHeartbeat" : ISODate("2017-11-22T13:55:27.684Z"), "lastHeartbeatRecv" : ISODate("2017-11-22T13:55:27.827Z"), "pingMs" : NumberLong(0), "configVersion" : 2 } ], "ok" : 1 } 或者使用該方法查看,結果也是同樣: rs0:PRIMARY> use admin switched to db admin rs0:PRIMARY> db.runCommand( { replSetGetStatus : 1 } ) { "set" : "rs0", "date" : ISODate("2017-11-23T01:12:20.701Z"), "myState" : 1, "term" : NumberLong(1), "heartbeatIntervalMillis" : NumberLong(2000), "members" : [ { "_id" : 0, "name" : "sign-mongo01.wangshibo.cn:27017", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 41643, "optime" : { "ts" : Timestamp(1511358895, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2017-11-22T13:54:55Z"), "electionTime" : Timestamp(1511358843, 2), "electionDate" : ISODate("2017-11-22T13:54:03Z"), "configVersion" : 2, "self" : true }, { "_id" : 1, "name" : "sign-mongo02.wangshibo.cn:27018", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 40645, "optime" : { "ts" : Timestamp(1511358895, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2017-11-22T13:54:55Z"), "lastHeartbeat" : ISODate("2017-11-23T01:12:19.418Z"), "lastHeartbeatRecv" : ISODate("2017-11-23T01:12:16.225Z"), "pingMs" : NumberLong(0), "configVersion" : 2 } ], "ok" : 1 } rs0:PRIMARY> 詳細說明以下: "_id" : #集羣中節點編號 "name" : #成員服務器名稱及端口 "health" : #表示成員中的健康狀態(0:down;1:up) "state" : #爲0~10,表示成員的當前狀態 "stateStr" : #描述該成員是主庫(PRIMARY)仍是備庫(SECONDARY) "uptime" : #該成員在線時間(秒) "optime" : #成員最後一次應用日誌(oplog)的信息 "optimeDate" : #成員最後一次應用日誌(oplog)的時間 "electionTime" : #當前primary從操做日誌中選舉信息 "electionDate" : #當前primary被選定爲primary的日期 "configVersion" : #mongodb版本 "self" : #爲true 表示當前節點 4)測試操做。在主庫中,能夠任意操做: rs0:PRIMARY> show dbs local 0.000GB rs0:PRIMARY> use mydb //切換到要建立的數據庫 switched to db mydb rs0:PRIMARY> show dbs //use只是轉到相關數據庫,此時並無作任何操做,因此並不會建立相應的數據庫,只有當真正的操做了一次數據庫就會自動建立。 local 0.000GB rs0:PRIMARY> db.stats(); { "db" : "mydb", "collections" : 0, "objects" : 0, "avgObjSize" : 0, "dataSize" : 0, "storageSize" : 0, "numExtents" : 0, "indexes" : 0, "indexSize" : 0, "fileSize" : 0, "ok" : 1 } rs0:PRIMARY> db.coll.insert({"id":1}) WriteResult({ "nInserted" : 1 }) rs0:PRIMARY> db.coll.find() { "_id" : ObjectId("5a162222991b83743942d169"), "id" : 1 } rs0:PRIMARY> db.coll.remove({"id":1}) WriteResult({ "nRemoved" : 1 }) rs0:PRIMARY> show dbs local 0.000GB mydb 0.000GB 如今到備庫中 172.16.51.217 (sign-mongo02.wangshibo.cn ) 查看分庫數據庫目錄,發現多了數據庫,數據庫與主庫(172.16.51.216)一致!是主庫同步過來的。 [app@sign-mongo02 ~]$ mongo 172.16.51.217:27018 MongoDB shell version: 3.2.17-34-g4c1bae566c connecting to: 172.16.51.217:27018/test Server has startup warnings: 2017-11-22T21:46:38.417+0800 I CONTROL [initandlisten] 2017-11-22T21:46:38.418+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'. 2017-11-22T21:46:38.418+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2017-11-22T21:46:38.418+0800 I CONTROL [initandlisten] 2017-11-22T21:46:38.418+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'. 2017-11-22T21:46:38.418+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2017-11-22T21:46:38.418+0800 I CONTROL [initandlisten] 在副本服務器中登陸其本地數據庫,發現能夠鏈接,可是沒法讀寫操做: rs0:SECONDARY> show dbs 2017-11-23T09:25:35.961+0800 E QUERY [thread1] Error: listDatabases failed:{ "ok" : 0, "errmsg" : "not master and slaveOk=false", "code" : 13435 } : _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:781:19 shellHelper@src/mongo/shell/utils.js:671:15 @(shellhelp2):1:1 rs0:SECONDARY> 從庫開啓讀操做(此時能夠測試主庫插入,從庫查看,同步正常): rs0:SECONDARY> rs.slaveOk(); rs0:SECONDARY> show dbs local 0.000GB mydb 0.000GB 5)如今模擬主庫不可用,將主節點服務中止: [app@sign-mongo01 mongodb]$ pkill -9 mongod [app@sign-mongo01 mongodb]$ ps -ef|grep mongodb app 9524 9398 0 09:32 pts/0 00:00:00 grep mongodb 到備節點172.16.51.217 中登陸mongodb,查看複製集狀態: [app@sign-mongo02 ~]$ mongo 172.16.51.217:27018 MongoDB shell version: 3.2.17-34-g4c1bae566c connecting to: 172.16.51.217:27018/test Server has startup warnings: 2017-11-22T21:46:38.417+0800 I CONTROL [initandlisten] 2017-11-22T21:46:38.418+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'. 2017-11-22T21:46:38.418+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2017-11-22T21:46:38.418+0800 I CONTROL [initandlisten] 2017-11-22T21:46:38.418+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'. 2017-11-22T21:46:38.418+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2017-11-22T21:46:38.418+0800 I CONTROL [initandlisten] rs0:SECONDARY> rs.status() { "set" : "rs0", "date" : ISODate("2017-11-23T01:33:29.688Z"), "myState" : 2, "term" : NumberLong(1), "heartbeatIntervalMillis" : NumberLong(2000), "members" : [ { "_id" : 0, "name" : "sign-mongo01.wangshibo.cn:27017", "health" : 0, "state" : 8, "stateStr" : "(not reachable/healthy)", "uptime" : 0, "optime" : { "ts" : Timestamp(0, 0), "t" : NumberLong(-1) }, "optimeDate" : ISODate("1970-01-01T00:00:00Z"), "lastHeartbeat" : ISODate("2017-11-23T01:33:28.732Z"), "lastHeartbeatRecv" : ISODate("2017-11-23T01:32:28.099Z"), "pingMs" : NumberLong(0), "lastHeartbeatMessage" : "Connection refused", "configVersion" : -1 }, { "_id" : 1, "name" : "sign-mongo02.wangshibo.cn:27018", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 42412, "optime" : { "ts" : Timestamp(1511399985, 1), "t" : NumberLong(1) }, "optimeDate" : ISODate("2017-11-23T01:19:45Z"), "infoMessage" : "could not find member to sync from", "configVersion" : 2, "self" : true } ], "ok" : 1 } 有上面可看出,主節點刪除服務進程,primary並無切換到備節點上: 再次啓動主節點的mongodb服務,發現primary才自動切換回到主節點: [app@sign-mongo01 mongodb]$ nohup /data/mongodb/bin/mongod --config /data/mongodb/mongodb.conf nohup: ignoring input and appending output to `nohup.out' [app@sign-mongo01 mongodb]$ ps -ef|grep mongodb app 9538 1 8 09:37 ? 00:00:00 /data/mongodb/bin/mongod --config /data/mongodb/mongodb.conf app 9610 9398 0 09:37 pts/0 00:00:00 grep mongodb [app@sign-mongo01 mongodb]$ mongo 172.16.51.216:27017 MongoDB shell version: 3.2.17-34-g4c1bae566c connecting to: 172.16.51.216:27017/test Server has startup warnings: 2017-11-23T09:37:26.467+0800 I CONTROL [initandlisten] 2017-11-23T09:37:26.467+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'. 2017-11-23T09:37:26.467+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2017-11-23T09:37:26.467+0800 I CONTROL [initandlisten] 2017-11-23T09:37:26.467+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'. 2017-11-23T09:37:26.467+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2017-11-23T09:37:26.467+0800 I CONTROL [initandlisten] rs0:PRIMARY> rs.status() { "set" : "rs0", "date" : ISODate("2017-11-23T01:38:19.631Z"), "myState" : 1, "term" : NumberLong(2), "heartbeatIntervalMillis" : NumberLong(2000), "members" : [ { "_id" : 0, "name" : "sign-mongo01.wangshibo.cn:27017", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 54, "optime" : { "ts" : Timestamp(1511401058, 2), "t" : NumberLong(2) }, "optimeDate" : ISODate("2017-11-23T01:37:38Z"), "infoMessage" : "could not find member to sync from", "electionTime" : Timestamp(1511401058, 1), "electionDate" : ISODate("2017-11-23T01:37:38Z"), "configVersion" : 2, "self" : true }, { "_id" : 1, "name" : "sign-mongo02.wangshibo.cn:27018", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 53, "optime" : { "ts" : Timestamp(1511401058, 2), "t" : NumberLong(2) }, "optimeDate" : ISODate("2017-11-23T01:37:38Z"), "lastHeartbeat" : ISODate("2017-11-23T01:38:18.072Z"), "lastHeartbeatRecv" : ISODate("2017-11-23T01:38:18.596Z"), "pingMs" : NumberLong(0), "syncingTo" : "sign-mongo01.wangshibo.cn:27017", "configVersion" : 2 } ], "ok" : 1 } +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 如今開始部署仲裁節點sign-mongo03.wangshibo.cn [app@sign-mongo03 ~]$ mkdir /data/mongodb/arbiter [app@sign-mongo03 ~]$ ll -d /data/mongodb/arbiter drwxrwxr-x 2 app app 4096 Nov 23 09:39 /data/mongodb/arbiter 本案例是在普通用戶app帳號下部署的,權限都是app.app。 若是是在root帳號下部署,那麼須要將mongodb數據目錄下的文件所有設置mongodb.mongodb權限 mongodb.conf配置: [app@sign-mongo03 ~]$ vim /data/mongodb/mongodb.conf pidfilepath=/data/mongodb/log/mongod.pid logpath=/data/mongodb/log/mongod.log dbpath=/data/mongodb/arbiter logappend=false bind_ip=172.16.51.218 port=27019 fork=true replSet=rs0 接着重啓服務: [app@sign-mongo03 ~]$ /data/mongodb/bin/mongod --config /data/mongodb/mongodb.conf about to fork child process, waiting until server is ready for connections. forked process: 9217 child process started successfully, parent exiting [app@sign-mongo03 ~]$ ps -ef|grep mongo app 9217 1 1 09:46 ? 00:00:00 /data/mongodb/bin/mongod --config /data/mongodb/mongodb.conf app 9242 9158 0 09:46 pts/0 00:00:00 grep mongo [app@sign-mongo03 ~]$ lsof -i:27019 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME mongod 9217 app 6u IPv4 37321 0t0 TCP sign-mongo03.wangshibo.cn:27019 (LISTEN) 而後在Paimary主節點sign-mongo01.wangshibo.cn的mongodb中添加仲裁節點並查看結果 [app@sign-mongo01 mongodb]$ mongo 172.16.51.216:27017 MongoDB shell version: 3.2.17-34-g4c1bae566c connecting to: 172.16.51.216:27017/test Server has startup warnings: 2017-11-23T09:37:26.467+0800 I CONTROL [initandlisten] 2017-11-23T09:37:26.467+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'. 2017-11-23T09:37:26.467+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2017-11-23T09:37:26.467+0800 I CONTROL [initandlisten] 2017-11-23T09:37:26.467+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'. 2017-11-23T09:37:26.467+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2017-11-23T09:37:26.467+0800 I CONTROL [initandlisten] rs0:PRIMARY> rs.addArb("sign-mongo03.wangshibo.cn:27019") { "ok" : 1 } rs0:PRIMARY> db.isMaster() { "hosts" : [ "sign-mongo01.wangshibo.cn:27017", "sign-mongo02.wangshibo.cn:27018" ], "arbiters" : [ "sign-mongo03.wangshibo.cn:27019" ], "setName" : "rs0", "setVersion" : 4, "ismaster" : true, "secondary" : false, "primary" : "sign-mongo01.wangshibo.cn:27017", "me" : "sign-mongo01.wangshibo.cn:27017", "electionId" : ObjectId("7fffffff0000000000000003"), "maxBsonObjectSize" : 16777216, "maxMessageSizeBytes" : 48000000, "maxWriteBatchSize" : 1000, "localTime" : ISODate("2017-11-23T01:59:03.554Z"), "maxWireVersion" : 4, "minWireVersion" : 0, "ok" : 1 } rs0:PRIMARY> rs.status() { "set" : "rs0", "date" : ISODate("2017-11-23T02:00:26.312Z"), "myState" : 1, "term" : NumberLong(3), "heartbeatIntervalMillis" : NumberLong(2000), "members" : [ { "_id" : 0, "name" : "sign-mongo01.wangshibo.cn:27017", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 368, "optime" : { "ts" : Timestamp(1511402420, 1), "t" : NumberLong(3) }, "optimeDate" : ISODate("2017-11-23T02:00:20Z"), "electionTime" : Timestamp(1511402069, 1), "electionDate" : ISODate("2017-11-23T01:54:29Z"), "configVersion" : 5, "self" : true }, { "_id" : 1, "name" : "sign-mongo02.wangshibo.cn:27018", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 367, "optime" : { "ts" : Timestamp(1511402420, 1), "t" : NumberLong(3) }, "optimeDate" : ISODate("2017-11-23T02:00:20Z"), "lastHeartbeat" : ISODate("2017-11-23T02:00:26.306Z"), "lastHeartbeatRecv" : ISODate("2017-11-23T02:00:26.309Z"), "pingMs" : NumberLong(0), "syncingTo" : "sign-mongo01.wangshibo.cn:27017", "configVersion" : 5 }, { "_id" : 3, "name" : "sign-mongo03.wangshibo.cn:27019", "health" : 1, "state" : 7, "stateStr" : "ARBITER", "uptime" : 93, "lastHeartbeat" : ISODate("2017-11-23T02:00:26.306Z"), "lastHeartbeatRecv" : ISODate("2017-11-23T02:00:25.306Z"), "pingMs" : NumberLong(0), "configVersion" : 5 } ], "ok" : 1 } 至此,添加完成!! 再次測試主備切換。關閉172.16.51.216(primary)中刪除服務進程: [app@sign-mongo01 mongodb]$ pkill -9 mongod [app@sign-mongo01 mongodb]$ ps -ef|grep mongod app 9664 9398 0 09:50 pts/0 00:00:00 grep mongod [app@sign-mongo01 mongodb]$ lsof -i:27017 [app@sign-mongo01 mongodb]$ 而後到172.16.51.217:27018(secondary)查看,發現primary已經切換爲172.16.51.217 [app@sign-mongo02 ~]$ mongo 172.16.51.217:27018 MongoDB shell version: 3.2.17-34-g4c1bae566c connecting to: 172.16.51.217:27018/test Server has startup warnings: 2017-11-22T21:46:38.417+0800 I CONTROL [initandlisten] 2017-11-22T21:46:38.418+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'. 2017-11-22T21:46:38.418+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2017-11-22T21:46:38.418+0800 I CONTROL [initandlisten] 2017-11-22T21:46:38.418+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'. 2017-11-22T21:46:38.418+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2017-11-22T21:46:38.418+0800 I CONTROL [initandlisten] rs0:PRIMARY> rs.status() { "set" : "rs0", "date" : ISODate("2017-11-23T02:01:17.762Z"), "myState" : 1, "term" : NumberLong(4), "heartbeatIntervalMillis" : NumberLong(2000), "members" : [ { "_id" : 0, "name" : "sign-mongo01.wangshibo.cn:27017", "health" : 0, "state" : 8, "stateStr" : "(not reachable/healthy)", "uptime" : 0, "optime" : { "ts" : Timestamp(0, 0), "t" : NumberLong(-1) }, "optimeDate" : ISODate("1970-01-01T00:00:00Z"), "lastHeartbeat" : ISODate("2017-11-23T02:01:17.316Z"), "lastHeartbeatRecv" : ISODate("2017-11-23T02:01:04.327Z"), "pingMs" : NumberLong(0), "lastHeartbeatMessage" : "Connection refused", "configVersion" : -1 }, { "_id" : 1, "name" : "sign-mongo02.wangshibo.cn:27018", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 44080, "optime" : { "ts" : Timestamp(1511402475, 2), "t" : NumberLong(4) }, "optimeDate" : ISODate("2017-11-23T02:01:15Z"), "infoMessage" : "could not find member to sync from", "electionTime" : Timestamp(1511402475, 1), "electionDate" : ISODate("2017-11-23T02:01:15Z"), "configVersion" : 5, "self" : true }, { "_id" : 3, "name" : "sign-mongo03.wangshibo.cn:27019", "health" : 1, "state" : 7, "stateStr" : "ARBITER", "uptime" : 145, "lastHeartbeat" : ISODate("2017-11-23T02:01:17.315Z"), "lastHeartbeatRecv" : ISODate("2017-11-23T02:01:15.316Z"), "pingMs" : NumberLong(0), "configVersion" : 5 } ], "ok" : 1 } rs0:PRIMARY> show dbs local 0.000GB mydb 0.000GB 有上面信息可知,添加仲裁節點後,primary能正常啓動切換了!~ 如今看看arbiter,鏈接到172.16.51.218:27019 [app@sign-mongo03 ~]$ mongo 172.16.51.218:27019 MongoDB shell version: 3.2.17-34-g4c1bae566c connecting to: 172.16.51.218:27019/test Welcome to the MongoDB shell. For interactive help, type "help". For more comprehensive documentation, see http://docs.mongodb.org/ Questions? Try the support group http://groups.google.com/group/mongodb-user Server has startup warnings: 2017-11-23T09:58:34.978+0800 I CONTROL [initandlisten] 2017-11-23T09:58:34.978+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'. 2017-11-23T09:58:34.978+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2017-11-23T09:58:34.978+0800 I CONTROL [initandlisten] 2017-11-23T09:58:34.978+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'. 2017-11-23T09:58:34.978+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2017-11-23T09:58:34.978+0800 I CONTROL [initandlisten] rs0:ARBITER> rs.slaveOk(); rs0:ARBITER> db.isMaster() { "hosts" : [ "sign-mongo01.wangshibo.cn:27017", "sign-mongo02.wangshibo.cn:27018" ], "arbiters" : [ "sign-mongo03.wangshibo.cn:27019" ], "setName" : "rs0", "setVersion" : 5, "ismaster" : false, "secondary" : false, "primary" : "sign-mongo02.wangshibo.cn:27018", "arbiterOnly" : true, "me" : "sign-mongo03.wangshibo.cn:27019", "maxBsonObjectSize" : 16777216, "maxMessageSizeBytes" : 48000000, "maxWriteBatchSize" : 1000, "localTime" : ISODate("2017-11-23T02:03:33.874Z"), "maxWireVersion" : 4, "minWireVersion" : 0, "ok" : 1 } rs0:ARBITER> show dbs local 0.000GB arbiter 最爲仲裁者,沒有數據副本存儲在本地,能讀取複製集的信息。 ------------------------------------------------------------------------------------------------- 在primary主庫上,建立locs數據庫,該庫的用戶名爲locsopr,密碼爲locsopr@123 [app@sign-mongo02 ~]$ mongo 172.16.51.217:27018 ...... rs0:PRIMARY> use locs switched to db locs rs0:PRIMARY> db.createUser({user:"locsopr",pwd :"locsopr@123",roles:["readWrite"]}) Successfully added user: { "user" : "locsopr", "roles" : [ "readWrite" ] } rs0:PRIMARY> show users; //查看當前庫下的用戶名 { "_id" : "locs.locsopr", "user" : "locsopr", "db" : "locs", "roles" : [ { "role" : "readWrite", "db" : "locs" } ] } 使用上面的用戶登陸primary主庫 [app@sign-mongo02 ~]$ mongo 172.16.51.217:27018/locs -ulocsopr -plocsopr@123 ......... rs0:PRIMARY> show users { "_id" : "locs.locsopr", "user" : "locsopr", "db" : "locs", "roles" : [ { "role" : "readWrite", "db" : "locs" } ] } rs0:PRIMARY> show dbs admin 0.000GB local 0.000GB rs0:PRIMARY> 再登陸從庫看下: [app@sign-mongo01 ~]$ mongo 172.16.51.216:27017/locs -ulocsopr -plocsopr@123 ....... rs0:SECONDARY> rs.slaveOk(); rs0:SECONDARY> show users { "_id" : "locs.locsopr", "user" : "locsopr", "db" : "locs", "roles" : [ { "role" : "readWrite", "db" : "locs" } ] } rs0:SECONDARY> show dbs admin 0.000GB local 0.000GB
-------------------------------------------------------------------------------------------------------------------------------------------------------
上面介紹的是三臺mongodb節點:一主一備一仲裁,這樣,主節點掛了後,經過仲裁機制將primary自動切換到備機上!
若是上面的三臺mongodb節點:一主兩備,沒有仲裁節點,那麼主節點掛了後,primary會自動切換到其他兩臺備節點中的一臺上!
一主兩從(端口分別爲2701七、2701八、27019)的mongodb配置和上面一主一從(端口分別爲2701七、27018)的配置同樣。 多加的一個從節點,在主節點登錄mongodb,使用rs.add命令將這個成員加到集羣中便可! 一主兩從的模式,好比: 主節點sign-mongo01.wangshibo.cn的mongodb服務程序掛了後,另外兩個從節點中的一個(好比sign-mongo02.wangshibo.cn)會自動變成primary主節點, 另外一個節點sign-mongo03.wangshibo.cn則是新的主節點(sign-mongo02.wangshibo.cn)的從節點。 ++++++++++++++++++++++++++++++若是想讓切換回原來的主節點,作法以下+++++++++++++++++++++++++++++++ 1)恢復原來的主節點sign-mongo01.wangshibo.cn的mongodb服務,使用命令rs.status() 確認數據集成員運行正常。 2)到次節點sign-mongo03.wangshibo.cn中登陸mongodb,運行freeze使其120內不會變爲主節點。 > rs.freeze(120) 3) 到新的主節點sign-mongo02.wangshibo.cn中強制切換主節點,stepDown將阻止長事務和寫入操做 > rs.stepDown(120) 4)此時sign-mongo01.wangshibo.cn節點變成primary主節點。使用rs.status()命令能夠查看到集羣狀態。 +++++++++++++++++++++++若要使某個節點永遠不會變爲主節點,設置優先級爲0便可+++++++++++++++++++++++ 登錄當前主節點的mongodb,執行下面操做: rs0:PRIMARY> cfg = rs.conf() rs0:PRIMARY> cfg.members[0].priority = 0.5 rs0:PRIMARY> cfg.members[1].priority = 0.5 rs0:PRIMARY> cfg.members[2].priority = 0 rs0:PRIMARY> rs.reconfig(cfg) 說明: 其中成員編號0/1/2爲 rs.status()中的 "_id"值 members[2]表示sign-mongo03.wangshibo.cn,則它將永遠不會變成主節點!由於優先級設置爲0了! ++++++++++++++++++++++++++++++++移除一個複製成員(兩種方法)++++++++++++++++++++++++++++++++++++ 登錄當前主節點的mongodb,執行下面操做: rs0:PRIMARY> rs.remove("sign-mongo03.wangshibo.cn:27019") rs0:PRIMARY> rs.conf() 或者: rs0:PRIMARY> cfg = rs.conf() rs0:PRIMARY> cfg.members.splice(2,1) rs0:PRIMARY> rs.reconfig(cfg) 移除後到移除的節點服務器(即sign-mongo03.wangshibo.cn),更改配置文件mongod.conf #replSet=rs0 //將這一行註釋 而後再重啓mongodb服務,這就完成了移除(數據庫文件仍保留在當前服務器)。