MongoDB數(shù)據(jù)庫(kù)的備份與恢復(fù)詳解
MongoDB是怎么實(shí)現(xiàn)數(shù)據(jù)的備份與恢復(fù),故障切換以及數(shù)據(jù)庫(kù)服務(wù)器的負(fù)載均衡等功能的呢?本文我們就介紹這些知識(shí)。
備份與恢復(fù)
在創(chuàng)建MongoDB服務(wù)的時(shí)候,通過(guò)--dbpath指定目錄就是存放mongdb數(shù)據(jù)庫(kù)文件目錄,我們可以通過(guò)復(fù)制這些文件實(shí)現(xiàn)數(shù)據(jù)庫(kù)的冷備,但是這種方式不太安全。因此在冷備前,要關(guān)閉服務(wù)器,這個(gè)在第一節(jié)中介紹過(guò)平滑關(guān)閉server的命令。
- >use admin
- >db.shutdownServer()
或者可以通過(guò)fsync方式使MongoDB將數(shù)據(jù)寫(xiě)入緩存中,然后再?gòu)?fù)制備份
- >use admin
- >db.runCommand({"fsync":1,"lock":1})
這個(gè)時(shí)候我往test.foo 插入了一條數(shù)據(jù) f:6 ,在執(zhí)行db.foo.find()后,并沒(méi)有查到這條記錄,說(shuō)明記錄沒(méi)有直接寫(xiě)入數(shù)據(jù)庫(kù),而是被緩沖到緩存中了。
備份完后,要解鎖(防止這個(gè)時(shí)候停電或其它原因,導(dǎo)致未緩存中的數(shù)據(jù)丟失)。
- >use admin
- >db.$cmd.sys.unlock.findOne()
- >db.currentOp() 如果currentOp 只返回{"inprog":[]}結(jié)果,說(shuō)明解鎖成功。
解鎖后,緩存中的數(shù)據(jù)會(huì)寫(xiě)入數(shù)據(jù)庫(kù)文件中,我們?nèi)ゲ樵僨oo結(jié)果。
上面是冷備的方式,我們可以在不停止服務(wù)的情況下,使用MongoDB提供的兩個(gè)工具來(lái)實(shí)現(xiàn)備份和恢復(fù)。這個(gè)兩個(gè)工具在MongoDB的bin目錄下可以看到:mongodump.exe/mongorestor.exe
mongodump.exe備份的原理是通過(guò)一次查詢獲取當(dāng)前服務(wù)器快照,并將快照寫(xiě)入磁盤(pán)中,因此這種方式保存的也不是實(shí)時(shí)的,因?yàn)樵讷@取快照后,服務(wù)器還會(huì)有數(shù)據(jù)寫(xiě)入,為了保證備份的安全,同樣我們還是可以利用fsync鎖使服務(wù)器數(shù)據(jù)暫時(shí)寫(xiě)入緩存中。
備份命令:
- ......bin>mongodump -d test -o backup //( backup是備份目錄,默認(rèn)創(chuàng)建到bin目錄)
恢復(fù)命令: (可以在恢復(fù)前往foo表插入一條記錄 g:7)
- .....bin>mongorestore -d test --drop backup/test/
看一下運(yùn)行結(jié)果:
以上就是mongodb的備份和恢復(fù)過(guò)程。當(dāng)數(shù)據(jù)庫(kù)文件出現(xiàn)問(wèn)題或者損壞時(shí),MongoDB還提供了修復(fù)數(shù)據(jù)文件的命令。
在啟動(dòng)mongod服務(wù)時(shí)通過(guò)--repair 修改:
- ....bin>mongod --dbpath "C:\Program Files\mongodb\data\dbs\master" --repair
另外我們也可以在mongo shell 中修復(fù)正在運(yùn)行的數(shù)據(jù)庫(kù)存
- >use test
- >db.repairDataBase()
#p#
接下來(lái)我們?cè)趤?lái)看一下另外二種讀擴(kuò)展式的備份機(jī)制。
Master-Slave
主從復(fù)制模式:即一臺(tái)主寫(xiě)入服務(wù)器,多臺(tái)從備份服務(wù)器。從服務(wù)器可以實(shí)現(xiàn)備份,和讀擴(kuò)展,分擔(dān)主服務(wù)器讀密集時(shí)壓力,充當(dāng)查詢服務(wù)器。但是主服務(wù)器故障時(shí),我們只能手動(dòng)去切換備份服務(wù)器接替主服務(wù)器工作。這種靈活的方式,使擴(kuò)展多如備份或查詢服務(wù)器相對(duì)比較容易,當(dāng)然查詢服務(wù)器也不是無(wú)限擴(kuò)展的,因?yàn)檫@些從服務(wù)器定期在輪詢讀取主服務(wù)器的更新,當(dāng)從服務(wù)器過(guò)多時(shí)反而會(huì)對(duì)主服務(wù)器造成過(guò)載。
我們以之前創(chuàng)建的端口為27017做為主服務(wù)器,再創(chuàng)建個(gè)端口為27018從服務(wù)器
重新啟動(dòng)27017為主服務(wù)器 --master 主服務(wù)器
- ....bin>mongod --dbpath "C:\Program Files\mongodb\data\dbs\master" --master
創(chuàng)建27018為從服務(wù)器 --slave 從服務(wù)器 --source 指定主服務(wù)器
- ....bin>mongod --port 27018 --dbpath "C:\Program Files\mongodb\data\dbs\slave27018" --slave --source localhost:27017
主服務(wù)器可以通過(guò)自己local庫(kù)的slave集合查看從服務(wù)器列表
從服務(wù)器可以通過(guò)自己local庫(kù)的source集合查看主服務(wù)器信息或維護(hù)多個(gè)主服務(wù)器。 (一個(gè)slave服務(wù)器可以服務(wù)多個(gè)master服務(wù)器)
或者我們可以通過(guò)http console查看狀態(tài)
Replica Sets
副本集模式:具有Master-Slave模式所有特點(diǎn),但是副本集沒(méi)有固定的主服務(wù)器,當(dāng)初始化的時(shí)候會(huì)通過(guò)多個(gè)服務(wù)器投票選舉出一個(gè)主服務(wù)器。當(dāng)主服務(wù)器故障時(shí)會(huì)再次通過(guò)投票選舉出新的主服務(wù)器,而原先的主服務(wù)器恢復(fù)后則轉(zhuǎn)為從服務(wù)器。Replica Sets的在故障發(fā)生時(shí)自動(dòng)切換的機(jī)制可以極時(shí)保證寫(xiě)入操作。
創(chuàng)建多個(gè)副本集節(jié)點(diǎn) --replSet (注意要區(qū)分大小寫(xiě),官方建議命名空間使用IP地址)
- ....bin>mongod --dbpath "C:\Program Files\mongodb\data\dbs\replset27017" --port 27017 --replSet replset/127.0.0.1:27018
- ....bin>mongod --dbpath "C:\Program Files\mongodb\data\dbs\replset27018" --port 27018 --replSet replset/127.0.0.1:27017
- ....bin>mongod --dbpath "C:\Program Files\mongodb\data\dbs\replset27019" --port 27019 --replSet replset/127.0.0.1:27017
首先建立3個(gè)是為了投票不會(huì)沖突,當(dāng)服務(wù)器為偶數(shù)時(shí)可能會(huì)導(dǎo)致無(wú)法正常選舉出主服務(wù)器。
其次上面3個(gè)replset 節(jié)點(diǎn)沒(méi)有全部串聯(lián)起來(lái),是因?yàn)閞eplset 有自檢測(cè)功可以自動(dòng)搜索連接其它服務(wù)器。
完成上面的工作后,要初始化副本集,隨便連接一臺(tái)服務(wù)器執(zhí)行以下命令 (priority 0~1,被選為主服務(wù)器的優(yōu)先級(jí))
- >use admin
- >db.runCommand(
- {"replSetInitiate":{
- "_id":"replset",
- "members":[
- {
- "_id":1,
- "host":"127.0.0.1:27017",
- "priority":1
- },
- {
- "_id":2,
- "host":"127.0.0.1:27018",
- "priority":1
- },
- {
- "_id":3,
- "host":"127.0.0.1:27019",
- "priority":1
- }]}}
- )
查看結(jié)果,可以看出127.0.0.1:27017 被自動(dòng)選為replSet:Primary>
在增加一個(gè)從服務(wù)器節(jié)點(diǎn)
- ....bin>mongod --dbpath "C:\Program Files\mongodb\data\dbs\replset27020" --port 27020 --replSet replset/127.0.0.1:27017
通過(guò)rs.add命令往system.replset添加新的從服務(wù)器成員
- rs.add("127.0.0.1:27020"); 或者rs.add({"_id":4,"host":"127.0.0.1:27020"})
這里在簡(jiǎn)單的介紹一下Master Slave/ Replica Sets 備份機(jī)制,這兩種模式都是基于主服務(wù)器的oplog 來(lái)實(shí)現(xiàn)所有從服務(wù)器的同步。
oplog記錄了增刪改操作的記錄信息(不包含查詢的操作),但是oplog有大小限制,當(dāng)超過(guò)指定大小,oplog會(huì)清空之前的記錄,重新開(kāi)始記錄。
Master Slave方式主服備器會(huì)產(chǎn)生 oplog.$main 的日志集合。
Replica Sets 方式 所有服務(wù)器都會(huì)產(chǎn)生oplog.rs 日志集合。
兩種機(jī)制下,所有從服務(wù)器都會(huì)去輪詢主服務(wù)器oplog日志,若主服務(wù)器的日志較新,就會(huì)同步這些新的操作記錄。但是這里有個(gè)很重要的問(wèn)題,從服務(wù)器由于網(wǎng)絡(luò)阻塞,死機(jī)等原因無(wú)法極時(shí)同步主服務(wù)器oplog記錄:一種情況 主服務(wù)器oplog不斷刷新,這樣從服務(wù)器永遠(yuǎn)無(wú)法追上主服務(wù)器。另外一種情況,剛好主服務(wù)器oplog超出大小,清空了之前的oplog,這樣從服務(wù)器就與主服務(wù)器數(shù)據(jù)就可能會(huì)不一致了,這第二種情況,我是推斷的,沒(méi)有證實(shí)。
另外要說(shuō)明一下Replica Sets 備份的缺點(diǎn),當(dāng)主服務(wù)器發(fā)生故障時(shí),一臺(tái)從服務(wù)器被投票選為了主服務(wù)器,但是這臺(tái)從服務(wù)的oplog 如果晚于之前的主服務(wù)器oplog的話,那之前的主服務(wù)器恢復(fù)后,會(huì)回滾自己的oplog操作和新的主服務(wù)器oplog保持一致。由于這個(gè)過(guò)程是自動(dòng)切換的,所以在無(wú)形之中就導(dǎo)致了部分?jǐn)?shù)據(jù)丟失。
關(guān)于MongoDB備份與恢復(fù)的知識(shí)就介紹到這里了,希望能夠帶給您收獲。
【編輯推薦】






