MongoDB 基礎(九)分區,mongodb基礎
分區(sharding)是通過多台伺服器儲存資料的方法。Mongodb使用分區可支援部署非常大的資料集和高的輸送量操作。單台伺服器的能力在各方面都有限,如CPU、IO、RAM、儲存空間等。解決擴充的問題,資料庫提供了兩種方法:垂直擴充和分區。
垂直擴充:增加CPU、RAM,儲存資源等,這也受限於硬體裝置。而有些雲端式的供應商也規定使用者使用小的系統。
分區(水平擴充):劃分資料集,將資料分布到多台伺服器中,每個片段(chard)是一個獨立的資料庫,這些片段共同組成了一個邏輯的資料庫。(這類似於Windows動態磁碟條帶化一樣)
Mongodb 中的分區叢集結構如下:
分區叢集有三個組件:shards,query routers 和 configservers。
Shards:片段,儲存資料,提供高可用性和資料的一致性。分區叢集中,每個片段都是一個複製集。
query routers:查詢路由,或稱mongos執行個體,用戶端應用程式直接操作片段的介面。查詢路由處理和定位操作到片段中並返回相關資料到用戶端。一個分區叢集包含多個查詢路由來劃分用戶端的請求壓力。
configservers:設定管理員,儲存叢集中的中繼資料。這些資料包含叢集資料到片段的映射。查詢路由使用這些中繼資料定位操作到明確的片段中。共用叢集需要有3台設定管理員。
註:用於測試,可以值配置1個config servers
Mongodb 分布資料或片段,是在collection 層級上。分區是通過shardkey 劃分一個集合的資料。shard key 可以是一個索引鍵列,或者是存在每個文檔中的複合鍵列。Mongodb 劃分shard key 值到 chunk 中,並將chunk平均分配到片段中。Mongodb 使用劃分的方法為定界分割或者雜湊分割。(更多參考:shardkey)
分區叢集部署:
Mongodb伺服器:(Red HatEnterprise Linux 6 64-bit + Mongodb 3.0.2)
192.168.1.11 mongodb11.kk.net 21017
192.168.1.12 mongodb12.kk.net 21018
192.168.1.13 mongodb13.kk.net 21019
192.168.1.14 mongodb14.kk.net 21020
用於測試結構如下:
註:配置前確保要加入叢集中的成員都能相互串連。
【1. 配置 config servers】(在 192.168.1.14伺服器上)
設定管理員(config servers)儲存叢集中繼資料,因此首先配置該伺服器。設定管理員需使用參數—configsvr 來啟動mongod服務。若有多個設定管理員,每個設定管理員都完整儲存叢集的元素就。
1. 1 建立資料庫目錄 configdb :
[root@mongodb14 ~]# mkdir /var/lib/mongo/configdb[root@mongodb14 ~]# chown mongod:mongod /var/lib/mongo/configdb/
1.2. 配置啟動參數檔案:
[root@mongodb14 ~]# vi /etc/mongod.conf
192.168.1.14 |
logpath=/var/log/mongodb/mongod.log pidfilepath=/var/run/mongodb/mongod.pid logappend=true fork=true port=27020 bind_ip=192.168.1.14 dbpath=/var/lib/mongo/configdb configsvr=true |
1.3. 重啟 mongod 服務:
[root@mongodb14 ~]# service mongod restart
【2. 配置 router】(在 192.168.1.11伺服器上)
2.1.啟用 mongos (MongoDB Shard)執行個體,串連到 config servers:(更多參考:mongos )
#使用mongos串連到config servers,指定本地連接埠,否則預設27017#當前伺服器mongod 連接埠為27017,所以配置mongos 連接埠為27016#mongo --host <hostname of machine running mongos> --port <port mongos listens on>[root@redhat11 ~]# mongos --configdb mongodb14.kk.net:27020 --port 27016 --chunkSize 200 --logpath /var/log/mongodb/mongos.log --fork
實際環境中,若配置了多個config servers ,mongos 可同時指定多個。
mongos--configdb mongodb14.kk.net:27020, mongodb15.kk.net:27020,mongodb16.kk.net:27020……
【3. 添加 shard 成員到叢集中】(添加IP為 11、12、13 分區集中 ,以192.168.1.11為例)
3.1. 配置啟動參數檔案:
[root@redhat11 ~]# vi /etc/mongod.conf
192.168.1.11 |
192.168.1.12 |
192.168.1.13 |
logpath=/var/log/mongodb/mongod.log pidfilepath=/var/run/mongodb/mongod.pid logappend=true fork=true port=27017 bind_ip=192.168.1.11 dbpath=/var/lib/mongo shardsvr=true |
logpath=/var/log/mongodb/mongod.log pidfilepath=/var/run/mongodb/mongod.pid logappend=true fork=true port=27018 bind_ip=192.168.1.12 dbpath=/var/lib/mongo shardsvr=true |
logpath=/var/log/mongodb/mongod.log pidfilepath=/var/run/mongodb/mongod.pid logappend=true fork=true port=27019 bind_ip=192.168.1.13 dbpath=/var/lib/mongo shardsvr=true |
3.2.重啟 mongod 服務:
[root@mongodb11 ~]# service mongod restart
3.3各shard 成員串連到mongos 執行個體中添加(添加前把已存在的使用者資料移走或者刪除):
[root@mongodb11 ~]# mongo 192.168.1.11:27016mongos> sh.addShard("mongodb11.kk.net:27017")mongos> sh.addShard("mongodb12.kk.net:27018")mongos> sh.addShard("mongodb13.kk.net:27019")
3.4添加完成!~串連到mongos可查看系統相關資訊:
configsvr> show dbsconfigsvr> use configconfigsvr> show collectionsconfigsvr> configsvr> db.mongos.find(){ "_id" : "mongodb11.kk.net:27016", "ping" : ISODate("2015-05-23T11:16:47.624Z"), "up" : 1221, "waiting" : true, "mongoVersion" : "3.0.2" }configsvr> configsvr> db.shards.find(){ "_id" : "shard0000", "host" : "mongodb11.kk.net:27017" }{ "_id" : "shard0001", "host" : "mongodb12.kk.net:27018" }{ "_id" : "shard0002", "host" : "mongodb13.kk.net:27019" }configsvr> configsvr> db.databases.find(){ "_id" : "admin", "partitioned" : false, "primary" : "config" }{ "_id" : "mydb", "partitioned" : false, "primary" : "shard0000" }{ "_id" : "test", "partitioned" : false, "primary" : "shard0000" }
【4. 對資料庫啟用分區】
4.1 當前可串連到 mongos 查看資料庫或者集合的分區情況(沒有分區):
mongos> db.stats()mongos> db.tab.stats()
4.2 對資料庫啟用分區功能:
[root@mongodb11 ~]# mongo 192.168.1.11:27016mongos> sh.enableSharding("test")#或者[root@mongodb11 ~]# mongo 192.168.1.11:27016mongos> use adminmongos> db.runCommand( { enableSharding: "test"} )
4.3 此時查看資料庫分區情況,partitioned 變為 “true”。
configsvr> use configswitched to db configconfigsvr> db.databases.find(){ "_id" : "admin", "partitioned" : false, "primary" : "config" }{ "_id" : "mydb", "partitioned" : true, "primary" : "shard0000" }{ "_id" : "test", "partitioned" : true, "primary" : "shard0000" }
啟用資料庫分區並沒有將資料進行分開,還需要對 collection 進行分區。
【5. 對集合啟用分區】
啟用前,有幾個問題需要考慮的:
1. 選擇哪個鍵列作為 shard key 。(更多參考: Considerations for Selecting Shard Keys)
2. 如果集合中已經存在資料,在選定作為shard key 的鍵列必須建立索引;如果集合為空白,mongodb 將在啟用集合分區(sh.shardCollection)時建立索引。
3. 集合分區函數 sh.shardCollection ,
sh.shardCollection("<database>.<collection>", shard-key-pattern)
mongos> sh.shardCollection("test.tab", { "_id": "hashed" })
測試:
for (var i=1; i<100000; i++) {db.kk.insert({"id": i, "myName" : "kk"+i, "myDate" : new Date()});}mongos> show collectionsmongos> db.kk.find()mongos> db.kk.createIndex({ "id": "hashed" })mongos> db.kk.getIndexes()mongos> sh.shardCollection("test.kk", { "id": "hashed" })mongos> db.stats()mongos> db.kk.stats()
由於資料分區需要時間,過會再查看資料分布情況:
總行數:99999
mongos> db.kk.count()99999
mongos> db.printShardingStatus();--- Sharding Status --- sharding version: {"_id" : 1,"minCompatibleVersion" : 5,"currentVersion" : 6,"clusterId" : ObjectId("556023c02c2ebfdfbc8d39eb")} shards:{ "_id" : "shard0000", "host" : "mongodb11.kk.net:27017" }{ "_id" : "shard0001", "host" : "mongodb12.kk.net:27018" }{ "_id" : "shard0002", "host" : "mongodb13.kk.net:27019" } balancer:Currently enabled: yesCurrently running: noFailed balancer rounds in last 5 attempts: 0Migration Results for the last 24 hours: 1334 : Success2 : Failed with error 'could not acquire collection lock for test.kk to migrate chunk [{ : MinKey },{ : MaxKey }) :: caused by :: Lock for migrating chunk [{ : MinKey }, { : MaxKey }) in test.kk is taken.', from shard0000 to shard0001 databases:{ "_id" : "admin", "partitioned" : false, "primary" : "config" }{ "_id" : "mydb", "partitioned" : true, "primary" : "shard0000" }{ "_id" : "test", "partitioned" : true, "primary" : "shard0000" }test.kkshard key: { "id" : "hashed" }chunks:shard0000667shard0001667shard0002667too many chunks to print, use verbose if you want to force print{ "_id" : "events", "partitioned" : false, "primary" : "shard0002" }mongos>
看這裡 chunks :
shard0000 667
shard0001 667
shard0002 667
原本 shard0000 最大,shard0001 與 shard0002 為 0 。最終平均,資料將穩定不再變化。
mongos> db.kk.stats(){"sharded" : true,"paddingFactorNote" : "paddingFactor is unused and unmaintained in 3.0. It remains hard coded to 1.0 for compatibility only.","userFlags" : 1,"capped" : false,"ns" : "test.kk","count" : 99999,"numExtents" : 19,"size" : 11199888,"storageSize" : 44871680,"totalIndexSize" : 10416224,"indexSizes" : {"_id_" : 4750256,"id_hashed" : 5665968},"avgObjSize" : 112,"nindexes" : 2,"nchunks" : 2001,"shards" : {"shard0000" : {"ns" : "test.kk","count" : 33500,"size" : 3752000,"avgObjSize" : 112,"numExtents" : 7,"storageSize" : 22507520,"lastExtentSize" : 11325440,"paddingFactor" : 1,"paddingFactorNote" : "paddingFactor is unused and unmaintained in 3.0. It remains hard coded to 1.0 for compatibility only.","userFlags" : 1,"capped" : false,"nindexes" : 2,"totalIndexSize" : 3605616,"indexSizes" : {"_id_" : 1913184,"id_hashed" : 1692432},"ok" : 1},"shard0001" : {"ns" : "test.kk","count" : 32852,"size" : 3679424,"avgObjSize" : 112,"numExtents" : 6,"storageSize" : 11182080,"lastExtentSize" : 8388608,"paddingFactor" : 1,"paddingFactorNote" : "paddingFactor is unused and unmaintained in 3.0. It remains hard coded to 1.0 for compatibility only.","userFlags" : 1,"capped" : false,"nindexes" : 2,"totalIndexSize" : 3343984,"indexSizes" : {"_id_" : 1389920,"id_hashed" : 1954064},"ok" : 1},"shard0002" : {"ns" : "test.kk","count" : 33647,"size" : 3768464,"avgObjSize" : 112,"numExtents" : 6,"storageSize" : 11182080,"lastExtentSize" : 8388608,"paddingFactor" : 1,"paddingFactorNote" : "paddingFactor is unused and unmaintained in 3.0. It remains hard coded to 1.0 for compatibility only.","userFlags" : 1,"capped" : false,"nindexes" : 2,"totalIndexSize" : 3466624,"indexSizes" : {"_id_" : 1447152,"id_hashed" : 2019472},"ok" : 1}},"ok" : 1}mongos>
上面中,個分區資料分布情況:
"shard0000" "count" : 33500
"shard0001" "count" : 32852
"shard0002" "count" : 33647
總計99999 行,完全準確,資料分布也很平均了。
(測試資料盡量多些,否則看不得效果。一開始本人測試資料較少,不到1000行,沒有效果,還以為哪裡出現問題,又多折騰了2小時!~)
參考: Sharding Introduction
(官方文檔的步驟不是很清楚,倒騰了好久。網上也有些部落格介紹,也只是博主的總結,對於一個新人來講,在哪操作,操作什麼不詳細)