前面幾篇文章的分析複製集解決了數據庫的備份與自動故障轉移,可是圍繞數據庫的業務中當前還有兩個方面的問題變得愈來愈重要。一是海量數據如何存儲?二是如何高效的讀寫海量數據?儘管複製集也能夠實現讀寫分析,如在primary節點上寫,在secondary節點上讀,但在這種方式下客戶端讀出來的數據有可能不是最新的,由於primary節點到secondary節點間的數據同步會帶來必定延遲,並且這種方式也不能處理大量數據。mongoDB從設計之初就考慮了上面所提到的兩個問題,引入了分片機制,實現了海量數據的分佈式存儲與高效的讀寫分離。複製集中的每一個成員是一個mongod實例,但在分片部署上,每個片可能就是一個複製集。mongodb
上面談到了分片的優勢,但分片的使用,會使數據庫系統變得複雜。何時使用分片也是須要考慮的問題。mongoDB使用內存映射文件的方式來讀寫數據庫,對內存的管理由操做系統來負責,隨着運行時間的推移,數據庫的索引和數據文件會變得愈來愈大,對於單節點的機器來講,早晚會突破內存的限制,當磁盤上的數據文件和索引遠大於內存的大小時,這個時候操做系統會頻繁的進行內存交換,致使整個數據庫系統的讀寫性能降低。所以對於大數據的處理,要時刻監控mongoDB的磁盤I/O性能、可用內存的大小,在數據庫內存使用率達到必定程度時就要考慮分片了。經過分片使整個數據庫分佈在各個片上,每一個片擁有數據庫的一部分數據,從而下降內存使用率,提升讀寫性能。數據庫
分片部署架構服務器
下面看看一個具體的分片部署架構是什麼,爲了後續的研究,先部署一個分片集羣。架構
分片集羣主要由mongos路由進程、複製集組成的片shards、一組配置服務器Configure構成,下面對這些模塊一一解釋。分佈式
分片集羣中的一個片shard實際上就是一個複製集,固然一個片也能夠是單個mongod實例,只是在分片集羣的生產環境中,每一個片只是保存整個數據庫數據的一部分,若是這部分數據丟失了,那麼整個數據庫就不完整了,所以應該保證每一個片上的數據穩定性和完整性,經過第7章對複製集的分析,複製集可以達到這樣的要求。所以經過將片配置爲複製集的形式,使片shard在默認狀況下讀寫都在複製集的primary節點上,每一個片同時具備自動故障轉移、冗餘備份的功能,總之複製集所具備的的特性在片上都能獲得體現。性能
mongos路由進程是一個輕量級且非持久性的進程。輕量級表示它不會保存任何數據庫中的數據,它只是將整個分片集羣當作一個總體,使分片集羣對整個客戶端程序來講是透明的,當客戶端發起讀寫操做時,由mongos路由進程將該操做路由到具體的片上進行;爲了實現對讀寫請求的路由,mongos進程必須知道整個分片集羣上全部數據庫的分片狀況即元信息,這些信息是從配置服務器上同步過來的,每次進程啓動時都會從configure服務器上讀元信息,mongos並不是持久化保存這些信息。大數據
配置服務器configure在整個分片集羣中想到重要,上面說到mongos會從配置服務器同步元信息,所以配置服務器要能實現這些元信息的持久化。配置服務器上的數據若是丟失,那麼整個分片集羣就沒法使用,所以在生產環境中一般利用三臺配置服務器來實現冗餘備份,這三臺服務器是獨立的,並非複製集架構。spa
下面按照上圖描述來配置一個這樣的分片集羣。操作系統
(1)配置複製集rs0並啓動,參考前面關於複製集中介紹的6個步驟。設計
先建立好rs0中各節點的數據文件存放路徑、日誌文件路徑以及配置文件,其中配置文件的內容以下:
rs0中primary節點的配置文件爲rs0_0.conf:
dbpath = E:\mongodb-win32-i386-2.4.3\db_rs0\data\rs0_0
logpath = E:\mongodb-win32-i386-2.4.3\db_rs0\logs\rs0_0.log
journal = true
port = 40000
replSet = rs0
rs0中secondary節點的配置文件爲rs0_1.conf:
dbpath = E:\mongodb-win32-i386-2.4.3\db_rs0\data\rs0_1
logpath = E:\mongodb-win32-i386-2.4.3\db_rs0\logs\rs0_1.log
journal = true
port = 40001
replSet = rs0
rs0中arbiter節點的配置文件爲rs0_2.conf:
dbpath = E:\mongodb-win32-i386-2.4.3\db_rs0\data\rs0_2
logpath = E:\mongodb-win32-i386-2.4.3\db_rs0\logs\rs0_2.log
journal = true
port = 40002
replSet = rs0
按照7.1節介紹的步驟啓動複製集rs0。
(2)配置複製集rs1並啓動,步驟與上面相同,這裏給出rs2中各節點對應的配置文件內容。
rs1中primary節點的配置文件爲rs1_0.conf:
dbpath = E:\mongodb-win32-i386-2.4.3\db_rs1\data\rs1_0
logpath = E:\mongodb-win32-i386-2.4.3\db_rs1\logs\rs1_0.log
journal = true
port = 40003
replSet = rs1
rs1中primary節點的配置文件爲rs1_1.conf:
dbpath = E:\mongodb-win32-i386-2.4.3\db_rs1\data\rs1_1
logpath = E:\mongodb-win32-i386-2.4.3\db_rs1\logs\rs1_1.log
journal = true
port = 40004
replSet = rs1
rs1中primary節點的配置文件爲rs1_2.conf:
dbpath = E:\mongodb-win32-i386-2.4.3\db_rs1\data\rs1_2
logpath = E:\mongodb-win32-i386-2.4.3\db_rs1\logs\rs1_2.log
journal = true
port = 40005
replSet = rs1
按照7.1節介紹的步驟啓動複製集rs0
經過rs.status()檢查並確認上述複製集已啓動且配置正確。
(3)配置configure服務器
configure服務器也是一個mongod進程,它與普通的mongod實例沒有本質區別,只是它上面的數據庫以及集合是特地給分片集羣用的,其內容會在後面詳細介紹。三個獨立的配置服務器對應的啓動配置文件內容以下:
configure服務器1的配置文件cfgserver_0.conf:
dbpath = E:\mongodb-win32-i386-2.4.3\db_configs\data\db_config0
logpath = E:\mongodb-win32-i386-2.4.3\db_configs\logs\db_config0.log
journal = true
port = 40006
configsvr = true
configure服務器2的配置文件cfgserver_1.conf:
dbpath = E:\mongodb-win32-i386-2.4.3\db_configs\data\db_config1
logpath = E:\mongodb-win32-i386-2.4.3\db_configs\logs\db_config1.log
journal = true
port = 40007
configsvr = true
configure服務器3的配置文件cfgserver_2.conf:
dbpath = E:\mongodb-win32-i386-2.4.3\db_configs\data\db_config2
logpath = E:\mongodb-win32-i386-2.4.3\db_configs\logs\db_config2.log
journal = true
port = 40008
configsvr = true
配置服務器上的mongod實例啓動時的配置選項與普通的mongod實例差很少,這裏只是多了一個configsvr=true的選擇,說明這個mongod實例是一個configure類型的mongod實例。
啓動上面三個配置服務器:
>mongod --config E:\mongodb-win32-i386-2.4.3\configs_cfgservers\cfgserver_0.conf
>mongod --config E:\mongodb-win32-i386-2.4.3\configs_cfgservers\cfgserver_1.conf
>mongod --config E:\mongodb-win32-i386-2.4.3\configs_cfgservers\cfgserver_2.conf
(4)配置mongos路由服務器
其配置文件cfg_mongos.conf內容爲:
logpath = E:\mongodb-win32-i386-2.4.3\mongos\logs\mongos.log
port = 40009
configdb = Guo:40006,GuO:40007,GuO:40008
啓動路由服務器:
>mongos --config E:\mongodb-win32-i386-2.4.3\mongos\cfg_mongos.conf
實例對應的進程爲mongos,路由服務器只是一個輕量級和非持久化操做的進程,所以上面的配置文件裏面沒有像其它mongod實例那樣有一個存放數據文件的路徑選項dbpath。
(5)添加各分片到集羣
上面已經完成了兩個片(複製集)、三個配置服務器、一個路由服務器且它已經知道從哪些配置服務器上同步元數據(configdb = Guo:40006,GuO:40007,GuO:40008),接下來要作的是將各個片添加到集羣中。
打開一個mongo客戶端鏈接到mongos服務器:
>mongo --port 40009
添加兩個分片
mongos> sh.addShard("rs0/GUO:40000,GUO:40001")
{ "shardAdded" : "rs0", "ok" : 1 }
mongos> sh.addShard("rs1/GUO:40003,GUO:40004")
{ "shardAdded" : "rs1", "ok" : 1 }
這裏添加分片的命令是sh.addShard(),參數是複製集名以及複製集中不包含arbiter類型的全部節點。
(6)最後經過命令sh.status()檢查上面的配置是否正確,正常的話輸出信息相似下面:
mongos> sh.status()
--- Sharding Status ---
sharding version: {
"_id" : 1,
"version" : 3,
"minCompatibleVersion" : 3,
"currentVersion" : 4,
"clusterId" : ObjectId("521b11e0a663075416070c04")
}
shards:
{ "_id" : "rs0", "host" : "rs0/Guo:40000,Guo:40001" }
{ "_id" : "rs1", "host" : "rs1/Guo:40003,Guo:40004" }
databases:
{ "_id" : "admin", "partitioned" : false, "primary" : "config" }
上面輸出的信息中clusterId字段表示此分片集羣的惟一標示;shards爲分片集羣中包含的全部片,其中_id爲此片的名稱,host爲片中的主機的host信息;databases爲集羣中的全部數據庫,其中_id爲數據庫名稱,partitioned表示此數據庫是否支持分片;primary表示當數據庫支持分片,此數據庫上全部未分片的集合所在的片。
此時在整個分片集羣中尚未建立任何其它數據庫,經過路由進程mongos鏈接集羣,執行命令show dbs能夠看到集羣中只有系統默認建立的一個config數據庫,且這個數據庫只存在於三個配置服務器上,config數據庫中的集合包含了整個集羣的配置信息,執行命令show collections,能夠看到有以下集合:
mongos> show collections
changelog:保存被分片的集合的任何元數據的改變,例如chunks的遷移、分割等。
Chunks:保存集羣中分片集合的全部塊的信息,包含塊的數據範圍與塊所在的片。
Databases:保存集羣中的全部數據庫,包含分片與未分片的。
Lockpings:保存跟蹤集羣中的激活組件。
locks:均衡器balancer執行時會生產鎖,在此集合中插入一條記錄。
mongos:保存了集羣中全部路由mongos的信息。
Settings:保存分片集羣的配置信息,如每一個chunk的大小(64MB)、均衡器的狀態。
Shards:保存了集羣中的全部片的信息。
system.indexes:保存config數據庫中的全部索引信息。
Version:保存當前全部元信息的版本。
由上所述得知,配置服務器中的config數據庫的信息對於整個集羣來講是相當重要的,這也是生產環境中最少須要3個配置服務器作冗餘備份的緣由;同時上面對config數據庫的全部操做,都是經過客戶端鏈接mongos後再進行的,儘管config數據庫也是在單個mongod實例上,咱們能夠直接經過客戶端鏈接到這個實例,而後作操做,可是這樣會出現配置服務器上的信息不一致的風險,所以咱們隊集羣的全部操做應該是經過客戶端鏈接mongos來執行。
最好探討一下實際部署的問題,經過上圖和前面的分析可知,一個生產環境的最少須要9個mongod實例進程,一個mongos進程實例,理論上說最少須要10臺機器才能組成。可是這些進程中有些並不須要不少軟硬件資源,它們能夠與其它進程共存部署在同一個機器上,如複製集中arbiter進程、mongos進程能夠部署到應用程序所在的服務器,綜合考慮後能夠獲得下面一個典型的部署:
圖8.2
上圖部署的整體原則是使每個片(複製集)中的primary節點、secondary節點、arbiter節點分開以及三臺配置服務器分開,當圖中的四臺機器任何一臺宕機後,集羣都可以正常運行。