前言
MongoDB是一個由C++語言編寫的基于分布式文件存儲的數據庫,是當前NoSQL數據庫中比較熱門的一種,旨在為Web應用提供可擴展的高性能數據存儲解決方案。本文介紹MongoDB復制集及數據分片。
MongoDB
簡介
MongoDB是一個介于關系數據庫和非關系數據庫之間的產品,是非關系數據庫當中功能最豐富,最像關系數據庫的。支持的數據結構非常松散,因此可以存儲比較復雜的數據類型。最大的特點是其支持的查詢語言非常強大,其語法有點類似于面向對象的查詢語言,幾乎可以實現類似關系數據庫單表查詢的絕大部分功能,而且還支持對數據建立索引。
特點及功能特性
特點:高性能、易部署、易使用,存儲數據非常方便
主要功能特性有:
面向集合存儲,易存儲對象類型的數據
模式自由
支持動態查詢
支持完全索引,包含內部對象
支持查詢
支持復制和故障恢復
使用高效的二進制數據存儲,包括大型對象(如視頻等)
自動處理碎片,以支持云計算層次的擴展性
支持Ruby,Python,Java,C++,PHP等多種語言
文件存儲格式為Bson(一種Json的擴展)
可通過網絡訪問
優缺點
與非關系型數據庫相比,MongoDB的優點:
弱一致性(最終一致),更能保證用戶的訪問速度
文檔結構的存儲方式,能夠更便捷的獲取數據
內置GridFS,支持大容量的存儲
內置Sharding
第三方支持豐富(這是與其他的NoSQL相比,MongoDB也具有的優勢)
性能優越
與非關系型數據庫相比,MongoDB的缺點:
不支持事務操作
占用空間過大
沒有成熟的維護工具
MongoDB復制集
復制集
MongoDB有兩種復制類型:Master/Slave主從和Replica Set副本集復制,由于MongoDB的特性,主從復制架構已基本不再使用,目前比較常見的是副本集復制方式
工作特性:
至少三個,且應該為奇數個節點,可使用arbiter(仲裁者)來參與選舉
復制集可實現失效自動轉移(通過選舉方式實現)
復制集的中特殊類型的節點:
0優先級的節點:冷備節點,不會被選舉成為主節點,但可以參與選舉
被隱藏的從節點:首先是一個0優先級的從節點,且對客戶端不可見
延遲復制的從節點:首先是一個0優先級的從節點,且復制時間落后于主節點一個固定時長
arbiter: 仲裁者
復制集架構
實驗拓撲
#系統環境:CentOS6.6 #各節點時間已同步
配置過程
安裝所需軟件
[root@node1 ~]# cd mongodb/ [root@node1 mongodb]# ls mongodb-org-server-2.6.10-1.x86_64.rpm mongodb-org-tools-2.6.10-1.x86_64.rpm mongodb-org-shell-2.6.10-1.x86_64.rpm [root@node1 mongodb]# yum install *.rpm -y #3個包都安裝 #所有節點都執行以上安裝操作
編輯配置文件
[root@node1 ~]# vim /etc/mongod.conf logpath=/var/log/mongodb/mongod.log logappend=true fork=true dbpath=/mongodb/data #數據位置 pidfilepath=/var/run/mongodb/mongod.pid #bind_ip=127.0.0.1 #默認監聽本機,注釋掉監聽所有 httpinterface=true #開放web rest=true replSet=testSet #復制集名,可自定義 replIndexPrefetch=_id_only
同步配置文件至各節點
[root@node1 ~]# scp /etc/mongod.conf node3:/etc root@node3's password: mongod.conf 100% 1567 1.5KB/s 00:00 [root@node1 ~]# scp /etc/mongod.conf node4:/etc root@node4's password: mongod.conf 100% 1567 1.5KB/s 00:00
創建數據目錄
[root@node1 ~]# mkdir /mongodb/data -pv mkdir: created directory `/mongodb' mkdir: created directory `/mongodb/data' [root@node1 ~]# chown -R mongod.mongod /mongodb #各節點都執行以上操作
啟動服務
[root@node1 ~]# service mongod start Starting mongod: [ OK ] [root@node1 mongodb]# ss -tnl | grep 27017 LISTEN 0 128 *:27017 *:* #各節點啟動服務,啟動過程中需要初始化數據,故啟動較慢
連接數據庫做初始化
[root@node1 ~]# mongo MongoDB shell version: 2.6.10 connecting to: 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 > rs.initiate() { "info2" : "no configuration explicitly specified -- making one", "me" : "node1.scholar.com:27017", "info" : "Config now saved locally. Should come online in about a minute.", "ok" : 1 } #初始化成功,查看狀態信息 > rs.status() { "set" : "testSet", "date" : ISODate("2015-07-13T12:33:27Z"), "myState" : 1, "members" : [ { "_id" : 0, "name" : "node1.scholar.com:27017", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 1111, "optime" : Timestamp(1436790736, 1), "optimeDate" : ISODate("2015-07-13T12:32:16Z"), "electionTime" : Timestamp(1436790737, 1), "electionDate" : ISODate("2015-07-13T12:32:17Z"), "self" : true } ], "ok" : 1 } testSet:PRIMARY> #已成為主節點
添加節點
testSet:PRIMARY> rs.add("172.16.10.125") { "ok" : 1 } testSet:PRIMARY> rs.add("172.16.10.126") { "ok" : 1 } #查看各節點狀態 testSet:PRIMARY> rs.status() { "set" : "testSet", "date" : ISODate("2015-07-13T12:41:07Z"), "myState" : 1, "members" : [ { "_id" : 0, "name" : "node1.scholar.com:27017", "health" : 1, "state" : 1, "stateStr" : "PRIMARY", "uptime" : 1571, "optime" : Timestamp(1436791178, 1), "optimeDate" : ISODate("2015-07-13T12:39:38Z"), "electionTime" : Timestamp(1436790737, 1), "electionDate" : ISODate("2015-07-13T12:32:17Z"), "self" : true }, { "_id" : 1, "name" : "172.16.10.125:27017", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 98, "optime" : Timestamp(1436791178, 1), "optimeDate" : ISODate("2015-07-13T12:39:38Z"), "lastHeartbeat" : ISODate("2015-07-13T12:41:06Z"), "lastHeartbeatRecv" : ISODate("2015-07-13T12:41:05Z"), "pingMs" : 1, "syncingTo" : "node1.scholar.com:27017" }, { "_id" : 2, "name" : "172.16.10.126:27017", "health" : 1, "state" : 2, "stateStr" : "SECONDARY", "uptime" : 89, "optime" : Timestamp(1436791178, 1), "optimeDate" : ISODate("2015-07-13T12:39:38Z"), "lastHeartbeat" : ISODate("2015-07-13T12:41:06Z"), "lastHeartbeatRecv" : ISODate("2015-07-13T12:41:06Z"), "pingMs" : 1, "syncingTo" : "node1.scholar.com:27017" } ], "ok" : 1 }
創建數據,驗證是否同步
#主節點 testSet:PRIMARY> use testdb switched to db testdb testSet:PRIMARY> db.students.insert({name: "ZhangSan",age: "21"}) WriteResult({ "nInserted" : 1 }) #從節點 testSet:SECONDARY> rs.slaveOk() #每個從節點首先申明從節點準備完畢才可同步 testSet:SECONDARY> use testdb switched to db testdb testSet:SECONDARY> show collections students system.indexes testSet:SECONDARY> db.students.findOne() { "_id" : ObjectId("55a3b494ebcafd9edbdfce4d"), "name" : "ZhangSan", "age" : "21" } #驗證從節點是否可寫 testSet:SECONDARY> db.classes.insert({class: "2",numstu: "50"}) WriteResult({ "writeError" : { "code" : undefined, "errmsg" : "not master" } }) #由此可見,只有主節點才可寫
以上便是復制集的相關配置,如果主節點故障,從節點會自動選舉出新的主節點,這里就不再演示
數據分片
分片緣由
分片(sharding)是MongoDB用來將大型集合分割到不同服務器(集群)上所采用的方法。當單臺服務器CPU,Memory,IO等無法滿足需求,就需要將數據分片存放,減緩服務器壓力。
分片架構
實驗拓撲
配置過程
因為以上做過實驗我們首先來清理一下數據
[root@node1 ~]# service mongod stop Stopping mongod: [ OK ] [root@node1 ~]# rm -rf /mongodb/data/* #各節點都執行以上操作,若第一次做可忽略
Config Server配置
#安裝所需包 [root@node2 mongodb]# ls mongodb-org-server-2.6.10-1.x86_64.rpm mongodb-org-tools-2.6.10-1.x86_64.rpm mongodb-org-shell-2.6.10-1.x86_64.rpm [root@node2 mongodb]# yum install *.rpm -y
修改配置文件
[root@node2 ~]# vim /etc//mongod.conf logpath=/var/log/mongodb/mongod.log logappend=true fork=true dbpath=/mongodb/data configsvr=true #開啟config server pidfilepath=/var/run/mongodb/mongod.pid #bind_ip=127.0.0.1 httpinterface=true rest=true
創建數據目錄
[root@node2 ~]# mkdir /mongodb/data -pv mkdir: created directory `/mongodb' mkdir: created directory `/mongodb/data' [root@node2 ~]# chown -R mongod.mongod /mongodb
啟動服務
[root@node2 ~]# service mongod start Starting mongod: [ OK ] [root@node2 ~]# ss -tnl | grep 27019 LISTEN 0 128 *:27019 *:* #監聽端口已發生改變,不再是27017
Mongos配置
#安裝所需包,Mongos節點只裝此包即可,無需裝第一次實驗中的mongod的相關包 [root@node1 ~]# yum install mongodb-org-mongos-2.6.10-1.x86_64.rpm -y
啟動服務
[root@node1 ~]# mongos --configdb=172.16.10.124 --fork --logpath=/var/log/mongodb/mongos.log 2015-07-13T22:22:47.404+0800 warning: running with 1 config server should be done only fo r testing purposes and is not recommended for production about to fork child process, waiting until server is ready for connections. forked process: 3583 child process started successfully, parent exiting #--configdb指定config server --logpath指定日志位置 --fork后臺運行
Shard配置
#以為我們第一次實驗安裝過軟件了,下面直接修改配置文件 [root@node3 ~]# vim /etc/mongod.conf logpath=/var/log/mongodb/mongod.log logappend=true fork=true dbpath=/mongodb/data pidfilepath=/var/run/mongodb/mongod.pid #bind_ip=127.0.0.1 httpinterface=true rest=true [root@node3 ~]# service mongod start Starting mongod: [ OK ] #兩個shard節點都執行以上操作
Mongos節點添加Shard節點
[root@node1 ~]# mongo --host 172.16.10.123 MongoDB shell version: 2.6.10 connecting to: 172.16.10.123:27017/test mongos> sh.addShard("172.16.10.125") { "shardAdded" : "shard0000", "ok" : 1 } mongos> sh.addShard("172.16.10.126") { "shardAdded" : "shard0001", "ok" : 1 } mongos> sh.status() --- Sharding Status --- sharding version: { "_id" : 1, "version" : 4, "minCompatibleVersion" : 4, "currentVersion" : 5, "clusterId" : ObjectId("55a3c9ba131b83ff44e19435") } shards: { "_id" : "shard0000", "host" : "172.16.10.125:27017" } { "_id" : "shard0001", "host" : "172.16.10.126:27017" } databases: { "_id" : "admin", "partitioned" : false, "primary" : "config" }
對所需對象啟用分片功能
#對數據庫啟用sharding功能 mongos> sh.enableSharding("testdb") { "ok" : 1 } mongos> sh.status() --- Sharding Status --- sharding version: { "_id" : 1, "version" : 4, "minCompatibleVersion" : 4, "currentVersion" : 5, "clusterId" : ObjectId("55a3c9ba131b83ff44e19435") } shards: { "_id" : "shard0000", "host" : "172.16.10.125:27017" } { "_id" : "shard0001", "host" : "172.16.10.126:27017" } databases: { "_id" : "admin", "partitioned" : false, "primary" : "config" } { "_id" : "test", "partitioned" : false, "primary" : "shard0000" } { "_id" : "testdb", "partitioned" : true, "primary" : "shard0000" } #指定需要分片的Collection及索引 mongos> sh.shardCollection("testdb.students",{"age": 1}) { "collectionsharded" : "testdb.students", "ok" : 1 } mongos> sh.status() --- Sharding Status --- sharding version: { "_id" : 1, "version" : 4, "minCompatibleVersion" : 4, "currentVersion" : 5, "clusterId" : ObjectId("55a3c9ba131b83ff44e19435") } shards: { "_id" : "shard0000", "host" : "172.16.10.125:27017" } { "_id" : "shard0001", "host" : "172.16.10.126:27017" } databases: { "_id" : "admin", "partitioned" : false, "primary" : "config" } { "_id" : "test", "partitioned" : false, "primary" : "shard0000" } { "_id" : "testdb", "partitioned" : true, "primary" : "shard0000" } testdb.students shard key: { "age" : 1 } chunks: shard0000 1 { "age" : { "$minKey" : 1 } } -->> { "age" : { "$maxKey" : 1 } } on : shard0000 Timestamp(1, 0)
分片功能已開啟,接下來我們手動創建數據來驗證是否會分片
mongos> use testdb switched to db testdb mongos> for (i=1;i<=100000;i++) db.students.insert({name:"student"+i,age:(i%120),addr:"china"}) WriteResult({ "nInserted" : 1 }) mongos> db.students.find().count() 100000 mongos> sh.status() --- Sharding Status --- sharding version: { "_id" : 1, "version" : 4, "minCompatibleVersion" : 4, "currentVersion" : 5, "clusterId" : ObjectId("55a3c9ba131b83ff44e19435") } shards: { "_id" : "shard0000", "host" : "172.16.10.125:27017" } { "_id" : "shard0001", "host" : "172.16.10.126:27017" } databases: { "_id" : "admin", "partitioned" : false, "primary" : "config" } { "_id" : "test", "partitioned" : false, "primary" : "shard0000" } { "_id" : "testdb", "partitioned" : true, "primary" : "shard0000" } testdb.students shard key: { "age" : 1 } chunks: shard0001 1 shard0000 2 { "age" : { "$minKey" : 1 } } -->> { "age" : 1 } on : shard0001 Timestamp(2, 0) { "age" : 1 } -->> { "age" : 119 } on : shard0000 Timestamp(2, 2) { "age" : 119 } -->> { "age" : { "$maxKey" : 1 } } on : shard0000 Timestamp(2, 3)
查看數據狀態會發現數據已被分到不同shard上,至此,數據分片成功實現
The end
MongoDB復制集及數據分片就先說到這里了,通過以上簡單應用可以看出,MongoDB在無論大數據處理還是復制方面都有著比MySQL更加優秀的性能和更加簡單的操作,但由于MongoDB目前還不是很成熟,在實際的應用中還有許多問題有待解決,相信在未來MongoDB會更加出色。以上僅為個人學習整理,如有錯漏,大神勿噴~~~
原創文章,作者:書生,如若轉載,請注明出處:http://www.www58058.com/6254