文章目錄
- 如果MongoDB僅僅是一個文檔型的資料庫,那就沒有什麼亮點了,然而MongoDB最大優點在於讀擴充,熱備份,故障恢複以及自動分區(寫擴充)。這節系列結束篇就把這些功能介紹一下。
- 1. 狀態監控
- 2.備份複製
- 3. 自動分區
如果MongoDB僅僅是一個文檔型的資料庫,那就沒有什麼亮點了,然而MongoDB最大優點在於讀擴充,熱備份,故障恢複以及自動分區(寫擴充)。這節系列結束篇就把這些功能介紹一下。
備份複製實現了Database Backup的同時,實現了讀寫分離,又實現了讀操作的負載平衡,即一台主寫伺服器,多台從屬備份和讀伺服器,並且支援備份和讀的叢集擴充。其中Replica Sets方式又支援故障切換,當主伺服器down掉後會投票選出一台從伺服器接替為主伺服器實現寫操作。而自動分區功能會將原先的集合(表),自動分區到其它伺服器上,實現分布式儲存,即緩解單表資料量過大,同時又實現寫操作的負載平衡。
- 狀態監控
- Http Console
- mongo Shell Diagnostic Commands
備份複製
- BackUp/Restore
- Master-Slave
- Replica Sets
自動分區
1. 狀態監控
首先分別在MongoDB目錄下分別建立data ,data\dbs(存放資料庫檔案目錄),data\dbs\master(主伺服器目錄),data\dbs\slave(從伺服器目錄)。
先以預設連接埠方式建立一個MongoDB資料庫服務
看最後兩行,預設建立的MongoDB服務監聽的是27017連接埠,而28017(監聽連接埠+1000) 是web admin interface 監聽連接埠,這個28017就是Http Console監控連接埠。
那就訪問一下這個http://localhost:28017/地址看看,為了顯示效果,先往預設的db.foo 資料添加幾條記錄
運行mongo.exe (預設串連的是測試庫test,裡面有個測試集合foo)
訪問http console(http://localhost:28017/)查看監控結果
注意紅色標記的地方,第一個標記在後面的備份複製會解釋,後面是動作記錄。
- mongo Shell Diagnostic Commands
再來通過mongo shell 指令碼來查詢服務器狀態
以上是兩種簡單的監控方式,當然還有更多的方式,可參考官方文檔這一節:Monitoring and Diagnostics
2.備份複製
不管是什麼資料庫都會考慮資料的備份複製,故障切換等。當一些資料庫伺服器讀寫比高時,我們還要考慮實現這些資料庫伺服器的負載平衡等功能。我們就來看看MongoDB是怎麼實現這些功能。
在建立MongoDB服務的時候,通過--dbpath指定目錄就是存放mongdb資料庫檔案目錄,我們可以通過複製這些檔案實現資料庫的冷備,但是這種方式不太安全。因此在冷備前,要關閉伺服器,這個在第一節中介紹過平滑關閉server的命令。
>use admin
>db.shutdownServer()
或者可以通過fsync方式使MongoDB將資料寫入緩衝中,然後再複本備份
>use admin
>db.runCommand({"fsync":1,"lock":1})
這個時候我往test.foo 插入了一條資料 f:6 ,在執行db.foo.find()後,並沒有查到這條記錄,說明記錄沒有直接寫入資料庫,而是被緩衝到緩衝中了。
備份完後,要解鎖(防止這個時候停電或其它原因,導致未緩衝中的資料丟失)
>use admin
>db.$cmd.sys.unlock.findOne()
>db.currentOp() 如果currentOp 只返回{"inprog":[]}結果,說明解鎖成功
解鎖後,緩衝中的資料會寫入資料庫檔案中,我們去查詢foo結果
上面是冷備的方式,我們可以在不停止服務的情況下,使用MongoDB提供的兩個工具來實現備份和恢複。這個兩個工具在MongoDB的bin目錄下可以看到
mongodump.exe/mongorestor.exe
mongodump.exe備份的原理是通過一次查詢擷取當前伺服器快照,並將快照寫入磁碟中,因此這種方式儲存的也不是即時的,因為在擷取快照後,伺服器還會有資料寫入,為了保證備份的安全,同樣我們還是可以利用fsync鎖使伺服器資料暫時寫入緩衝中。
備份命令:
......bin>mongodump -d test -o backup //( backup是備份目錄,預設建立到bin目錄)
恢複命令: (可以在恢複前往foo表插入一條記錄 g:7)
.....bin>mongorestore -d test --drop backup/test/
看一下運行結果:
以上是就是mongodb的備份和恢複過程。當資料庫檔案出現問題或者損壞時,MongoDB還提供了修複資料檔案的命令
在啟動mongod服務時通過--repair 修改
....bin>mongod --dbpath "C:\Program Files\mongodb\data\dbs\master" --repair
另外我們也可以在mongo shell 中修複正在啟動並執行資料庫存
>use test
>db.repairDataBase()
詳細細節可參照官網這一節:Backups
我們在來看一下另外二種讀擴充式的備份機制
主從複製模式:即一台主寫入伺服器,多台從備份伺服器。從伺服器可以實現備份,和讀擴充,分擔主伺服器讀密集時壓力,充當查詢服務器。但是主伺服器故障時,我們只能手動去切換備份伺服器接替主伺服器工作。這種靈活的方式,使擴充多如備份或查詢服務器相對比較容易,當然查詢服務器也不是無限擴充的,因為這些從伺服器定期在輪詢讀取主伺服器的更新,當從伺服器過多時反而會對主伺服器造成過載。
我們以之前建立的連接埠為27017做為主伺服器,再建立個連接埠為27018從伺服器
重新啟動27017為主伺服器 --master 主伺服器
....bin>mongod --dbpath "C:\Program Files\mongodb\data\dbs\master" --master
建立27018為從伺服器 --slave 從伺服器 --source 指定主伺服器
....bin>mongod --port 27018 --dbpath "C:\Program Files\mongodb\data\dbs\slave27018" --slave --source localhost:27017
主伺服器可以通過自己local庫的slave集合查看從伺服器列表
從伺服器可以通過自己local庫的source集合查看主伺服器資訊或維護多個主伺服器。 (一個slave伺服器可以服務多個master伺服器)
或者我們可以通過http console查看狀態
詳細可參照官網:Master Slave
複本集模式:具有Master-Slave模式所有特點,但是複本集沒有固定的主伺服器,當初始化的時候會通過多個伺服器投票選舉出一個主伺服器。當主伺服器故障時會再次通過投票選舉出新的主伺服器,而原先的主伺服器恢複後則轉為從伺服器。Replica Sets的在故障發生時自動切換的機制可以極時保證寫入操作。
建立多個複本集節點 --replSet (注意要區分大小寫,官方建議命名空間使用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個是為了投票不會衝突,當伺服器為偶數時可能會導致無法正常選舉出主伺服器。
其次上面3個replset 節點沒有全部串聯起來,是因為replset 有自檢測功可以自動搜尋串連其它伺服器。
完成上面的工作後,要初始化複本集,隨便串連一台伺服器執行以下命令 (priority 0~1,被選為主伺服器的優先順序)
>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
}]}}
)
查看結果,可以看出127.0.0.1:27017 被自動選為replSet:Primary>
在增加一個從伺服器節點
....bin>mongod --dbpath "C:\Program Files\mongodb\data\dbs\replset27020" --port 27020 --replSet replset/127.0.0.1:27017
通過rs.add命令往system.replset添加新的從伺服器成員
rs.add("127.0.0.1:27020"); 或者rs.add({"_id":4,"host":"127.0.0.1:27020"})
Replica Sets 介紹就到這裡了,詳細可參照官網:Replica Sets
這裡在簡單的介紹一下
Master Slave/ Replica Sets 備份機制,這兩種模式都是基於主伺服器的oplog 來實現所有從伺服器的同步。
oplog記錄了增刪改操作的記錄資訊(不包含查詢的操作),但是oplog有大小限制,當超過指定大小,oplog會清空之前的記錄,重新開始記錄。
Master Slave 方式 主服備器會產生 oplog.$main 的日誌集合
Replica Sets 方式 所有伺服器都會產生oplog.rs 日誌集合
兩種機制下,所有從伺服器都會去輪詢主伺服器oplog日誌,若主伺服器的日誌較新,就會同步這些新的操作記錄。但是這裡有個很重要的問題,從伺服器由於網路阻塞,死機等原因無法極時同步主伺服器oplog記錄:一種情況 主伺服器oplog不斷重新整理,這樣從伺服器永遠無法追上主伺服器。另外一種情況,剛好主伺服器oplog超出大小,清空了之前的oplog,這樣從伺服器就與主伺服器資料就可能會不一致了,這第二種情況,我是推斷的,沒有證實。
另外要說明一下Replica Sets 備份的缺點,當主伺服器發生故障時,一台從伺服器被投票選為了主伺服器,但是這台從服務的oplog 如果晚於之前的主伺服器oplog的話,那之前的主伺服器恢複後,會復原自己的oplog操作和新的主伺服器oplog保持一致。由於這個過程是自動切換的,所以在無形之中就導致了部分資料丟失。
3. 自動分區
自動分區:將原先資料庫中集合依據一定的規則切分成若干小塊,這些分區小塊統一由mongos路由管理,當有請求查詢或寫入時,路由會依據分區shard key規則找到對應的分區操作。分區解決了寫密集操作,用於分散單一寫伺服器負載。亦或者原先的儲存空間不夠了,這個時候可能通過分區操作將之後的資料寫入其它儲存空間上。可以看出,集合的分區和資料庫的分表類似,並且每個分區都支援寫操作。由於分區的出現,導致資料被分布式的儲存到不同的伺服器上,當某一伺服器出現問題時就可能導致資料丟失,其次路由mongos也會出現問題,另外儲存分區的資訊的設定管理員也可能會發生問題。當然我們可以利用master salve/Replica sets機制去備份每個分區、Mongos、configs 。如下官網配置圖示,即使我們使用伺服器交叉備份也需要大量的伺服器資源,因此分區是一件極具耗費資源的事情。官網的配置圖示
首先路由從config中讀取配置資訊,發生的分區動態增加也會通過mongos寫入config servres中,當client有請求時通過mongos尋找到對應的分區。可以看出分區使用的replica set備份模式,而mongos/config servrs則是多個伺服器配置。(詳細內容見官網:Sharding),下面就手動實現一下分區的過程。(換環境了繼續昨天未完成的,前2天在筆記本上)
1)建立configs伺服器
....bin>mongod --dbpath "e:\mongodb\data\configs" --port 23017
2)建立mongos伺服器 並指定依賴的設定管理員 (mongos依賴於設定管理員,mongos查詢的分區資訊都儲存在configs中)
....bin>mongos --port 25017 --configdb 127.0.0.1:23017
3)建立多個分區伺服器 (負責資料存放區)
....bin>mongod --port 27017 --dbpath "e:\mongodb\data\dbs\shard27017"
為shard27017分區伺服器 建立test庫foo集合,並且為foo集建立name索引
4)串連mongos 伺服器 添加shard27017分區伺服器到configs伺服器中
>use admin
>db.runCommand({addshard:"127.0.0.1:27017",allowLoacl:true}) //添加分區伺服器,allowLoacl 充許本地部署 預設情況不充許本地部署多個分區的
一旦分區添加成功,在mongos伺服器中執行 show dbs就可以看到分區伺服器的資料庫,並且可以操作分區伺服器的資料 ,下面為分區伺服器的test庫foo集合設定分區以及分區shard key。
>db.runCommand({"enablesharding":"test"}) //對test庫啟用分區功能
注意:需要分區的集合 的shard key必須是索引鍵, (我們也可以在mongos為分區foo集合建立索引)
>db.runCommand({"shardcollection":"test.foo","key":{"name":1}}) //數字代表排序
至此自動分區就建立完成了,可以在mongos或configs伺服器查詢分區資訊
當一個分區伺服器儲存不夠時,通過像3)方式繼續添加分區伺服器,monogs會自實現這些分區的叢集工作。
當需要移除分區時運行下面的命令,同時mongos路由會將此分區伺服器上的資訊移到其它分區上。
>db.runCommand({"removeshard":"127.0.0.1:27017"})
簡單的分析一下這個shard key,當不是寫密集操作時,而僅僅是因為儲存空間不夠了,這個shard key我們可以選用一些無上限範圍的key,如建立時間等,這樣新建立的記錄都會寫入新的分區伺服器上。
當需要使每個分區均勻分布資料時,或者寫入密集時,最好選用有一定範圍值的key ,當然這個範圍不能太小,像性別,真假等,這會導致只自動產生兩個分區,所以一定要選擇合適的shard key才能達到理想的效果。
MongoDB 擁有強大的讀寫擴充能力,而且配置比較靈活容易。雖然上面提到的這些功能,每一種都有一定的缺點,但是這些缺點可以通過合理設計歸避的。比如備份,因為備份是要消耗一定主服務性器效能,這個時候可以通過備份從伺服器,來避免影響到主伺服器效能。比如 oplog雖然有大小限制,我們可以通過觀察主伺服器連續一段時間(周/月/年)更新操作,來確定一個合適的oplog大小,以便從伺服器不會丟失對這些操作記錄的同步。亦或者每天某段時間強制主伺服器的寫入快取作業,以便從伺服器可以同步追趕上主伺服器。Mongodb入門就到此結束了。具體想瞭解更多,可以照官方文檔和論壇(文檔很詳細,樣本也很簡潔,即使命令錯語,也能根據提示資訊找到解決方案,Mongodb入門還是容易的)。
MongoDB系列導航