1. 程式人生 > 實用技巧 >MongoDB主從複製

MongoDB主從複製

介紹了Mongodb的安裝使用,在 MongoDB 中,有兩種資料冗餘方式,一種 是 Master-Slave 模式(主從複製),一種是 Replica Sets 模式(副本集)。

Mongodb一共有三種叢集搭建的方式:
Replica Set(副本集)、
Sharding(切片)
Master-Slaver(主從)【目前已不推薦使用了!!!】
 
其中,Sharding叢集也是三種叢集中最複雜的。
副本集比起主從可以實現故障轉移!!非常使用!
 
mongoDB目前已不推薦使用主從模式,取而代之的是副本集模式。副本集其實一種互為主從的關係,可理解為主主。
副本集指將資料複製,多份儲存,不同伺服器儲存同一份資料,在出現故障時自動切換。對應的是資料冗餘、備份、映象、讀寫分離、高可用性等關鍵詞;
而分片則指為處理大量資料,將資料分開儲存,不同伺服器儲存不同的資料,它們的資料總和即為整個資料集。追求的是高效能。
 
在生產環境中,通常是這兩種技術結合使用,分片
+副本集。

mongodb主從複製配置

有些版本已經不支援主從複製(本人環境為mongodb4.0版本,已經不支援主從複製)

主從複製是MongoDB最常用的複製方式,也是一個簡單的資料庫同步備份的叢集技術,這種方式很靈活.可用於備份,故障恢復,讀擴充套件等.
最基本的設定方式就是建立一個主節點和一個或多個從節點,每個從節點要知道主節點的地址。採用雙機備份後主節點掛掉了後從節點可以接替主機繼續服務。所以這種模式比單節點的高可用性要好很多。

配置主從複製的注意點

1)在資料庫叢集中要明確的知道誰是主伺服器,主伺服器只有一臺.
2)從伺服器要知道自己的資料來源也就是對應的主服務是誰.
3)--master用來確定主伺服器,--slave 和 --source 來控制從伺服器

可以在mongodb.conf配置檔案裡指明主從關係,這樣啟動mongodb的時候只要跟上配置檔案就行,就不需要通過--master和--slave來指明主從了。

下面簡單記錄下Mongodb主從複製的部署過程

1)機器環境
182.48.115.238    master-node
182.48.115.236    slave-node
 
兩臺機器都關閉防火牆和selinux
mongodb的安裝參考:http://www.cnblogs.com/kevingrace/p/5752382.html
 
2)主從配置
.............master-node節點配置.............
[root@master
-node ~]# vim /usr/local/mongodb/mongodb.conf port=27017 bind_ip = 182.48.115.238 dbpath=/usr/local/mongodb/data logpath=/usr/local/mongodb/log/mongo.log logappend=true journal = true fork = true master = true //確定自己是主伺服器 [root@master-node ~]# nohup /usr/local/mongodb/bin/mongod --config /usr/local/mongodb/mongodb.conf & [root@master-node ~]# ps -ef|grep mongodb root 15707 15514 23 16:45 pts/2 00:00:00 /usr/local/mongodb/bin/mongod --config /usr/local/mongodb/mongodb.conf root 15736 15514 0 16:45 pts/2 00:00:00 grep mongodb [root@master-node ~]# lsof -i:27017 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME mongod 15707 root 7u IPv4 153114 0t0 TCP 182.48.115.238:27017 (LISTEN) 由於mongodb.conf裡綁定了本機的ip地址182.48.115.238,所以連線mongodb的時候必須用這個ip地址,不能使用預設的127.0.0.1,也就是說: [root@master-node ~]# mongo 182.48.115.238:27017 //這樣才能連線mongodb [root@master-node ~]# mongo 或者 mongodb 127.0.0.1:27017 // 這樣不能連線mongodb .............slave-node節點配置............. [root@slave-node ~]# vim /usr/local/mongodb/mongodb.conf port=27017 dbpath=/usr/local/mongodb/data logpath=/usr/local/mongodb/log/mongo.log logappend=true journal = true fork = true bind_ip = 182.48.115.236 //確定主資料庫埠 source = 182.48.115.238:27017 //確定主資料庫埠 slave = true //確定自己是從伺服器 [root@slave-node ~]# nohup /usr/local/mongodb/bin/mongod --config /usr/local/mongodb/mongodb.conf & [root@slave-node ~]# ps -ef|grep mongo root 26290 26126 8 16:47 pts/0 00:00:00 /usr/local/mongodb/bin/mongod --config /usr/local/mongodb/mongodb.conf root 26316 26126 0 16:47 pts/0 00:00:00 grep mongo [root@slave-node ~]# lsof -i:27017 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME mongod 26290 root 7u IPv4 663904 0t0 TCP slave-node1:27017 (LISTEN) mongod 26290 root 25u IPv4 663917 0t0 TCP slave-node1:51060->slave-node2:27017 (ESTABLISHED) 在slave-node測試連線master-node的mongodb資料庫是否正常 [root@slave-node ~]# mongo 182.48.115.236:27017 MongoDB shell version v3.4.4 connecting to: 182.48.115.236:27017 MongoDB server version: 3.4.4 Server has startup warnings: 2017-06-03T16:47:31.200+0800 I STORAGE [initandlisten] 2017-06-03T16:47:31.200+0800 I STORAGE [initandlisten] ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine 2017-06-03T16:47:31.200+0800 I STORAGE [initandlisten] ** See http://dochub.mongodb.org/core/prodnotes-filesystem 2017-06-03T16:47:32.472+0800 I CONTROL [initandlisten] 2017-06-03T16:47:32.472+0800 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database. 2017-06-03T16:47:32.472+0800 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted. 2017-06-03T16:47:32.472+0800 I CONTROL [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended. 2017-06-03T16:47:32.472+0800 I CONTROL [initandlisten] 2017-06-03T16:47:32.473+0800 I CONTROL [initandlisten] 2017-06-03T16:47:32.473+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'. 2017-06-03T16:47:32.473+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2017-06-03T16:47:32.473+0800 I CONTROL [initandlisten] 2017-06-03T16:47:32.473+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'. 2017-06-03T16:47:32.473+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2017-06-03T16:47:32.473+0800 I CONTROL [initandlisten] > 3)主從資料同步測試 在master-node節點資料庫裡建立master_slave庫,並插入20條資料 [root@master-node ~]# mongo 182.48.115.238:27017 MongoDB shell version v3.4.4 connecting to: 182.48.115.238:27017 MongoDB server version: 3.4.4 Server has startup warnings: 2017-06-03T16:45:07.406+0800 I STORAGE [initandlisten] 2017-06-03T16:45:07.407+0800 I STORAGE [initandlisten] ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine 2017-06-03T16:45:07.407+0800 I STORAGE [initandlisten] ** See http://dochub.mongodb.org/core/prodnotes-filesystem 2017-06-03T16:45:08.373+0800 I CONTROL [initandlisten] 2017-06-03T16:45:08.373+0800 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database. 2017-06-03T16:45:08.373+0800 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted. 2017-06-03T16:45:08.373+0800 I CONTROL [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended. 2017-06-03T16:45:08.373+0800 I CONTROL [initandlisten] 2017-06-03T16:45:08.374+0800 I CONTROL [initandlisten] 2017-06-03T16:45:08.374+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'. 2017-06-03T16:45:08.374+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2017-06-03T16:45:08.374+0800 I CONTROL [initandlisten] 2017-06-03T16:45:08.374+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'. 2017-06-03T16:45:08.374+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2017-06-03T16:45:08.374+0800 I CONTROL [initandlisten] > use master_slave switched to db master_slave > function add(){var i = 0;for(;i<20;i++){db.persons.insert({"name":"wang"+i})}} > add() > db.persons.find() { "_id" : ObjectId("593278699a9e2e9f37ac4dbb"), "name" : "wang0" } { "_id" : ObjectId("593278699a9e2e9f37ac4dbc"), "name" : "wang1" } { "_id" : ObjectId("593278699a9e2e9f37ac4dbd"), "name" : "wang2" } { "_id" : ObjectId("593278699a9e2e9f37ac4dbe"), "name" : "wang3" } { "_id" : ObjectId("593278699a9e2e9f37ac4dbf"), "name" : "wang4" } { "_id" : ObjectId("593278699a9e2e9f37ac4dc0"), "name" : "wang5" } { "_id" : ObjectId("593278699a9e2e9f37ac4dc1"), "name" : "wang6" } { "_id" : ObjectId("593278699a9e2e9f37ac4dc2"), "name" : "wang7" } { "_id" : ObjectId("593278699a9e2e9f37ac4dc3"), "name" : "wang8" } { "_id" : ObjectId("593278699a9e2e9f37ac4dc4"), "name" : "wang9" } { "_id" : ObjectId("593278699a9e2e9f37ac4dc5"), "name" : "wang10" } { "_id" : ObjectId("593278699a9e2e9f37ac4dc6"), "name" : "wang11" } { "_id" : ObjectId("593278699a9e2e9f37ac4dc7"), "name" : "wang12" } { "_id" : ObjectId("593278699a9e2e9f37ac4dc8"), "name" : "wang13" } { "_id" : ObjectId("593278699a9e2e9f37ac4dc9"), "name" : "wang14" } { "_id" : ObjectId("593278699a9e2e9f37ac4dca"), "name" : "wang15" } { "_id" : ObjectId("593278699a9e2e9f37ac4dcb"), "name" : "wang16" } { "_id" : ObjectId("593278699a9e2e9f37ac4dcc"), "name" : "wang17" } { "_id" : ObjectId("593278699a9e2e9f37ac4dcd"), "name" : "wang18" } { "_id" : ObjectId("593278699a9e2e9f37ac4dce"), "name" : "wang19" } Type "it" for more 然後在slave-node節點資料庫裡檢視,是否將master-node寫入的新資料同步過來了 [root@slave-node log]# mongo 182.48.115.236:27017 MongoDB shell version v3.4.4 connecting to: 182.48.115.236:27017 MongoDB server version: 3.4.4 Server has startup warnings: 2017-06-03T16:56:28.928+0800 I STORAGE [initandlisten] 2017-06-03T16:56:28.928+0800 I STORAGE [initandlisten] ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine 2017-06-03T16:56:28.928+0800 I STORAGE [initandlisten] ** See http://dochub.mongodb.org/core/prodnotes-filesystem 2017-06-03T16:56:29.883+0800 I CONTROL [initandlisten] 2017-06-03T16:56:29.883+0800 I CONTROL [initandlisten] ** WARNING: Access control is not enabled for the database. 2017-06-03T16:56:29.883+0800 I CONTROL [initandlisten] ** Read and write access to data and configuration is unrestricted. 2017-06-03T16:56:29.883+0800 I CONTROL [initandlisten] ** WARNING: You are running this process as the root user, which is not recommended. 2017-06-03T16:56:29.883+0800 I CONTROL [initandlisten] 2017-06-03T16:56:29.884+0800 I CONTROL [initandlisten] 2017-06-03T16:56:29.884+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always'. 2017-06-03T16:56:29.884+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2017-06-03T16:56:29.884+0800 I CONTROL [initandlisten] 2017-06-03T16:56:29.884+0800 I CONTROL [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'. 2017-06-03T16:56:29.884+0800 I CONTROL [initandlisten] ** We suggest setting it to 'never' 2017-06-03T16:56:29.884+0800 I CONTROL [initandlisten] > show dbs 2017-06-03T17:10:32.136+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:769:19 shellHelper@src/mongo/shell/utils.js:659:15 @(shellhelp2):1:1 > rs.slaveOk(); > show dbs admin 0.000GB local 0.000GB master_slave 0.000GB wangshibo 0.000GB > use master_slave switched to db master_slave > db.persons.find() { "_id" : ObjectId("593278699a9e2e9f37ac4dbb"), "name" : "wang0" } { "_id" : ObjectId("593278699a9e2e9f37ac4dbc"), "name" : "wang1" } { "_id" : ObjectId("593278699a9e2e9f37ac4dbd"), "name" : "wang2" } { "_id" : ObjectId("593278699a9e2e9f37ac4dbe"), "name" : "wang3" } { "_id" : ObjectId("593278699a9e2e9f37ac4dbf"), "name" : "wang4" } { "_id" : ObjectId("593278699a9e2e9f37ac4dc0"), "name" : "wang5" } { "_id" : ObjectId("593278699a9e2e9f37ac4dc1"), "name" : "wang6" } { "_id" : ObjectId("593278699a9e2e9f37ac4dc2"), "name" : "wang7" } { "_id" : ObjectId("593278699a9e2e9f37ac4dc3"), "name" : "wang8" } { "_id" : ObjectId("593278699a9e2e9f37ac4dc4"), "name" : "wang9" } { "_id" : ObjectId("593278699a9e2e9f37ac4dc5"), "name" : "wang10" } { "_id" : ObjectId("593278699a9e2e9f37ac4dc6"), "name" : "wang11" } { "_id" : ObjectId("593278699a9e2e9f37ac4dc7"), "name" : "wang12" } { "_id" : ObjectId("593278699a9e2e9f37ac4dc8"), "name" : "wang13" } { "_id" : ObjectId("593278699a9e2e9f37ac4dc9"), "name" : "wang14" } { "_id" : ObjectId("593278699a9e2e9f37ac4dca"), "name" : "wang15" } { "_id" : ObjectId("593278699a9e2e9f37ac4dcb"), "name" : "wang16" } { "_id" : ObjectId("593278699a9e2e9f37ac4dcc"), "name" : "wang17" } { "_id" : ObjectId("593278699a9e2e9f37ac4dcd"), "name" : "wang18" } { "_id" : ObjectId("593278699a9e2e9f37ac4dce"), "name" : "wang19" } Type "it" for more ........................................................................................ 如果在slave-node節點上的資料庫中檢視,有報錯:"errmsg" : "not master and slaveOk=false"!!! 首先這是正常的,因為SECONDARY是不允許讀寫的, 在寫多讀少的應用中,使用Replica Sets來實現讀寫分離。 通過在連線時指定或者在主庫指定slaveOk,由Secondary來分擔讀的壓力,Primary只承擔寫操作。 對於replica set 中的secondary 節點預設是不可讀的。 解決辦法: 在slave-node節點資料庫中執行"rs.slaveOk();"命令即可 ........................................................................................ 在slave-node節點資料庫中發現已經同步過來了master_slave庫的20條資料,說明mongodb的主從複製環境已經成功了!當配置完主從伺服器後,一但主伺服器上的資料發生變化,從伺服器也會發生變化

主從複製的原理

在主從結構中,主節點的操作記錄成為oplog(operation log)。oplog儲存在一個系統資料庫local的集合oplog.$main中,這個集合的每個文件都代表主節點上執行的一個操作。
從伺服器會定期從主伺服器中獲取oplog記錄,然後在本機上執行!對於儲存oplog的集合,MongoDB採用的是固定集合,也就是說隨著操作過多,新的操作會覆蓋舊的操作!
 
主從複製的其他設定項
--only             從節點指定複製某個資料庫,預設是複製全部資料庫
--slavedelay       從節點設定主資料庫同步資料的延遲(單位是秒)
--fastsync         從節點以主資料庫的節點快照為節點啟動從資料庫
--autoresync       從節點如果不同步則從新同步資料庫(即選擇當通過熱添加了一臺從伺服器之後,從伺服器選擇是否更新主伺服器之間的資料)
--oplogSize        主節點設定oplog的大小(主節點操作記錄儲存到local的oplog中)

在上面slave-node從節點的local資料庫中,存在一個集合sources。這個集合就儲存了這個伺服器的主伺服器是誰

[root@slave-node mongodb]# mongo 182.48.115.236:27017
......
> show dbs
admin         0.000GB
local         0.000GB
master_slave  0.000GB
wangshibo     0.000GB
> use local
switched to db local
> show collections
me
sources
startup_log
> db.sources.find()
{ "_id" : ObjectId("593277a5105051e5648605a3"), "host" : "182.48.115.238:27017", "source" : "main", "syncedTo" : Timestamp(1496481652, 1) }
>