標籤:mongodb、mongodb分區
參考:http://www.lanceyan.com/tech/arch/mongodb_shard1.html
一、mongodb分區簡介
在系統早期,資料量還小的時候不會引起太大的問題,但是隨著資料量持續增多,後續遲早會出現一台機器硬體瓶頸問題的。而mongodb主打的就是海量資料架構,他不能解決海量資料怎麼行!不行!“分區”就用這個來解決這個問題。 傳統資料庫怎麼做海量資料讀寫?其實一句話概括:分而治之。看看就清楚了,如下 taobao嶽旭強在infoq中提到的 架構圖:
650) this.width=650;" title="clipboard.png" src="http://s3.51cto.com/wyfs02/M01/75/22/wKioL1YzNV3QH_eNAAErqxdop7k266.jpg" alt="wKioL1YzNV3QH_eNAAErqxdop7k266.jpg" />
中有個TDDL,是taobao的一個資料訪問層組件,他主要的作用是SQL解析、路由處理。根據應用的請求的功能解析當前訪問的sql判斷是在哪個業務資料庫、哪個表訪問查詢並返回資料結果。具體
650) this.width=650;" title="2.png" src="http://s3.51cto.com/wyfs02/M00/75/24/wKiom1YzNUGQUFeeAAFCk54sGLQ120.jpg" alt="wKiom1YzNUGQUFeeAAFCk54sGLQ120.jpg" />
說了這麼多傳統資料庫的架構,那Nosql怎麼去做到了這些呢?mysql要做到自動擴充需要加一個資料訪問層用程式去擴充,資料庫的增加、刪除、備份還需要程式去控制。一但資料庫的節點一多,要維護起來也是非常頭疼的。不過mongodb所有的這一切通過他自己的內部機制就可以搞定!還是看看mongodb通過哪些機制實現路由、分區:
650) this.width=650;" title="3.png" src="http://s3.51cto.com/wyfs02/M02/75/24/wKiom1YzNXXC88VfAAFAlXxMgCk553.jpg" alt="wKiom1YzNXXC88VfAAFAlXxMgCk553.jpg" />
可以看到有四個組件:mongos、config server、shard、replica set。
mongos,資料庫叢集請求的入口,所有的請求都通過mongos進行協調,不需要在應用程式添加一個路由選取器,mongos自己就是一個請求分發中心,它負責把對應的資料請求請求轉寄到對應的shard伺服器上。在生產環境通常有多mongos作為請求的入口,防止其中一個掛掉所有的mongodb請求都沒有辦法操作。
config server,顧名思義為設定管理員,儲存所有資料庫元資訊(路由、分區)的配置。mongos本身沒有實體儲存體分區伺服器和資料路由資訊,只是緩衝在記憶體裡,設定管理員則實際儲存這些資料。mongos第一次啟動或者關掉重啟就會從 config server 載入配置資訊,以後如果設定管理員資訊變化會通知到所有的 mongos 更新自己的狀態,這樣 mongos 就能繼續準確路由。在生產環境通常有多個 config server 設定管理員,因為它儲存了分區路由的中繼資料,這個可不能丟失!就算掛掉其中一台,只要還有存貨, mongodb叢集就不會掛掉。
shard,這就是傳說中的分區了。上面提到一個機器就算能力再大也有天花板,就像軍隊打仗一樣,一個人再厲害喝血瓶也拼不過對方的一個師。俗話說三個臭皮匠頂個諸葛亮,這個時候團隊的力量就凸顯出來了。在互連網也是這樣,一台普通的機器做不了的多台機器來做,如:
650) this.width=650;" title="4.png" src="http://s3.51cto.com/wyfs02/M01/75/22/wKioL1YzNcbSWYrHAADct7J8acA360.jpg" alt="wKioL1YzNcbSWYrHAADct7J8acA360.jpg" />
一台機器的一個資料表 Collection1 儲存了 1T 資料,壓力太大了!在分給4個機器後,每個機器都是256G,則分攤了集中在一台機器的壓力。也許有人問一台機器硬碟加大一點不就可以了,為什麼要分給四台機器呢?不要光想到儲存空間,實際啟動並執行資料庫還有硬碟的讀寫、網路的IO、CPU和記憶體的瓶頸。在mongodb叢集只要設定好了分區規則,通過mongos操作資料庫就能自動把對應的資料操作請求轉寄到對應的分區機器上。在生產環境中分區的片鍵可要好好設定,這個影響到了怎麼把資料均勻分到多個分區機器上,不要出現其中一台機器分了1T,其他機器沒有分到的情況,這樣還不如不分區!
分區的一些名詞解釋:
片鍵 :當設定分區時,需要從集合裡面選擇一個或幾個鍵,把選擇出來的鍵作為資料拆分的依據,這個鍵叫做片鍵或複合片鍵。 選好片鍵後,MongoDB將不允許插入沒有片鍵的文檔,但是允許不同文檔的片鍵類型不一樣。
塊(chunk) :在一個shard server內部,MongoDB還是會把資料分為chunks,每個chunk代表這個shard server內部一部分資料。chunk的產生,會有以下兩個用途:
二、環境搭建
1、實驗環境介紹
650) this.width=650;" title="5.png" src="http://s3.51cto.com/wyfs02/M00/75/24/wKiom1YzNaeg1CPLAAF4qF7HfQE648.jpg" alt="wKiom1YzNaeg1CPLAAF4qF7HfQE648.jpg" />
2、同步時間
[[email protected] ~]# ntpdate 202.120.2.101[[email protected] ~]# ntpdate 202.120.2.101[[email protected] ~]# ntpdate 202.120.2.101[[email protected] ~]# ntpdate 202.120.2.101
3、安裝mongodb
注意剩下三台前面已經安裝了mongodb這裡就不列舉了。
[[email protected] ~]# yum localinstall -y mongo-10gen-2.4.14-mongodb_1.x86_64.rpm mongo-10gen-server-2.4.14-mongodb_1.x86_64.rpm
4、配置config server
[[email protected] ~]# vim /etc/mongod.conf dbpath=/data/mongodbconfigsvr = true[[email protected] ~]# mkdir -p /data/mongodb[[email protected] ~]# chown -R mongod.mongod /data/mongodb[[email protected] ~]# service mongod startStarting mongod: about to fork child process, waiting until server is ready for connections.forked process: 130046all output going to: /var/log/mongo/mongod.log child process started successfully, parent exiting [確定][[email protected] ~]# ss -tnlp |grep mongodLISTEN 0 128 *:28019 *:* users:(("mongod",130046,10))LISTEN 0 128 *:27019 *:* users:(("mongod",130046,9))
5、配置mongos
注意在前面做複本集實驗時已經使用該機器,這裡需要將在做複本集實驗時的配置刪除,並按以下配置。
[[email protected] ~]# vim /etc/mongod.conf #dbpath=/data/mongodbconfigdb = 192.168.1.6:27019[[email protected] ~]# mongos -f /etc/mongod.confSat Sep 26 21:50:57.282 warning: running with 1 config server should be done only for testing purposes and is not recommended for productionabout to fork child process, waiting until server is ready for connections.forked process: 7485all output going to: /var/log/mongo/mongod.logchild process started successfully, parent exiting[[email protected] ~]# ss -tnlp |grep mongosLISTEN 0 128 *:28017 *:* users:(("mongos",7485,8))LISTEN 0 128 *:27017 *:* users:(("mongos",7485,6))
6、shard節點配置並啟動
node1和node2節點也是在前面做複本集的實驗中使用過,這裡需要將在前面所增加的配置給刪除,並按以下配置。
[[email protected] ~]# vim /etc/mongod.conf dbpath=/data/mongodb[[email protected] ~]# service mongod start[[email protected] ~]# vim /etc/mongod.conf dbpath=/data/mongodb[[email protected] ~]# service mongod start
7、連入mongos
[[email protected] ~]# mongo --host 192.168.1.8MongoDB shell version: 2.4.14connecting to: 192.168.1.8:27017/testmongos> sh.status()--- Sharding Status --- sharding version: { "_id" : 1, "version" : 3, "minCompatibleVersion" : 3, "currentVersion" : 4, "clusterId" : ObjectId("5606a2c30b2c688bc754432d")} shards: databases: { "_id" : "admin", "partitioned" : false, "primary" : "config" }添加shard節點:mongos> sh.addShard("192.168.1.9:27017"){ "shardAdded" : "shard0000", "ok" : 1 }mongos> sh.addShard("192.168.1.10:27017"){ "shardAdded" : "shard0001", "ok" : 1 }mongos> sh.status()--- Sharding Status --- sharding version: { "_id" : 1, "version" : 3, "minCompatibleVersion" : 3, "currentVersion" : 4, "clusterId" : ObjectId("5606a2c30b2c688bc754432d")} shards: { "_id" : "shard0000", "host" : "192.168.1.9:27017" } { "_id" : "shard0001", "host" : "192.168.1.10:27017" } databases: { "_id" : "admin", "partitioned" : false, "primary" : "config" } { "_id" : "test", "partitioned" : false, "primary" : "shard0000" }
將testdb庫分區:
mongos> sh.enableSharding("testdb"){ "ok" : 1 }mongos> use testdbswitched to db testdbmongos> sh.shardCollection("testdb.testcoll",{Age: 1,Name: 1}){ "collectionsharded" : "testdb.testcoll", "ok" : 1 }mongos> sh.status()--- Sharding Status --- sharding version: { "_id" : 1, "version" : 3, "minCompatibleVersion" : 3, "currentVersion" : 4, "clusterId" : ObjectId("5606a2c30b2c688bc754432d")} shards: { "_id" : "shard0000", "host" : "192.168.1.9:27017" } { "_id" : "shard0001", "host" : "192.168.1.10:27017" } databases: { "_id" : "admin", "partitioned" : false, "primary" : "config" } { "_id" : "test", "partitioned" : false, "primary" : "shard0000" } { "_id" : "testdb", "partitioned" : true, "primary" : "shard0001" } testdb.testcoll shard key: { "Age" : 1, "Name" : 1 } chunks: shard0001 1 { "Age" : { "$minKey" : 1 }, "Name" : { "$minKey" : 1 } } -->> { "Age" : { "$maxKey" : 1 }, "Name" : { "$maxKey" : 1 } } on : shard0001 Timestamp(1, 0)
增加資料用來查看是否能分區:
mongos> for(i=1;i<=1000000;i++) db.testcoll.insert({Name: "User"+i,Age:(i%150),Address: "xinyang"})
另一台機器接入mongos,查看輸入存放狀態:
[[email protected] ~]# mongo --host 192.168.1.8MongoDB shell version: 2.4.14connecting to: 192.168.1.8:27017/testmongos> use testdbswitched to db testdbmongos> sh.status()--- Sharding Status --- sharding version: { "_id" : 1, "version" : 3, "minCompatibleVersion" : 3, "currentVersion" : 4, "clusterId" : ObjectId("5606a2c30b2c688bc754432d")} shards: { "_id" : "shard0000", "host" : "192.168.1.9:27017" } { "_id" : "shard0001", "host" : "192.168.1.10:27017" } databases: { "_id" : "admin", "partitioned" : false, "primary" : "config" } { "_id" : "test", "partitioned" : false, "primary" : "shard0000" } { "_id" : "testdb", "partitioned" : true, "primary" : "shard0001" } testdb.testcoll shard key: { "Age" : 1, "Name" : 1 } chunks: shard0000 1 shard0001 3 { "Age" : { "$minKey" : 1 }, "Name" : { "$minKey" : 1 } } -->> { "Age" : 1, "Name" : "User1" } on : shard0000 Timestamp(2, 0) { "Age" : 1, "Name" : "User1" } -->> { "Age" : 64, "Name" : "User92614" } on : shard0001 Timestamp(2, 2) { "Age" : 64, "Name" : "User92614" } -->> { "Age" : 149, "Name" : "User899" } on : shard0001 Timestamp(2, 3) { "Age" : 149, "Name" : "User899" } -->> { "Age" : { "$maxKey" : 1 }, "Name" : { "$maxKey" : 1 } } on : shard0001 Timestamp(1, 4) mongos> db.testcoll.find({Age: {$gt: 140}}).limit(3){ "_id" : ObjectId("5606b672ef76b4db97a7d713"), "Name" : "User100041", "Age" : 141, "Address" : "xinyang" }{ "_id" : ObjectId("5606b672ef76b4db97a7d7a9"), "Name" : "User100191", "Age" : 141, "Address" : "xinyang" }{ "_id" : ObjectId("5606b672ef76b4db97a7d83f"), "Name" : "User100341", "Age" : 141, "Address" : "xinyang" }mongos> sh.getBalancerState()true
總結:
這裡只是簡單的示範了mongodb的分區機制,在該實驗中有幾點問題需要解決:
以上就是我所想到的問題點,然而實際中還是有很多問題需要解決,本人水平有限,這裡就不多說了,下面一個串連講的架構就是利用三台機器做到的shard的高可用,但實際中還是不建議這麼玩,在所有的分布式系統中建議還是增加主機使用,若機器較少,還是使用集中式的解決方案。畢竟關係型資料庫技術是很成熟的,而所有的nosql也是這幾年火起來的,若想使用還是要看公司的研發能力。個人認為在使用任何一個新技術術時一定不要盲目使用,需要看其缺點,而不是只看優點,同時根據自身的需求選擇軟體。只有最合適的沒有最好的!我在使用四台虛擬機器做該實驗時本本是4G的記憶體,CPU是i5-5200U,可是還是卡的要死,所以夥伴們還是根據自身的硬體在玩mongodb吧,我這隻是拋磚引玉。
650) this.width=650;" title="6.png" src="http://s3.51cto.com/wyfs02/M00/75/24/wKiom1YzNcqjHGoaAAG5UMOnqlc205.jpg" alt="wKiom1YzNcqjHGoaAAG5UMOnqlc205.jpg" />
本文出自 “粗茶淡飯” 部落格,請務必保留此出處http://cuchadanfan.blog.51cto.com/9940284/1708143
MongoDB(五)之分區