註:本文是研究Mongodb分布式資料存放區的副產品,通過本文的相關步驟可以將一個大表中的資料分布到幾個mongo伺服器上。
MongoDB的1.6版本中auto-sharding功能基本穩定並可以嘗試放到生產環境下使用。因為其是auto-sharding,即mongodb通過mongos(一個自動分區模組,用於構建一個大規模的可擴充的資料庫叢集,這個叢集可以併入動態增加的機器)自動建立一個水平擴充的資料庫叢集系統,將資料庫分表格儲存體在sharding的各個節點上。
一個mongodb叢集包括一些shards(包括一些mongod進程),mongos路由進程,一個或多個config伺服器
(註:本文的測試案例需求64位的mongo程式,因為我在32位的mongo沒成功過)。
下面是一些相關詞彙說明:
Shards : 每一個shard包括一個或多個服務和儲存資料的mongod進程(mongod是MongoDB資料的核心進程)典型的每個shard開啟多個服務來提高服務的可用性。這些服務/mongod進程在shard中組成一個複製集
Chunks: Chunk是一個來自特殊集合中的一個資料範圍,(collection,minKey,maxKey)描敘一個chunk,它介於minKey和maxKey範圍之間。例如chunks 的maxsize大小是100M,如果一個檔案達到或超過這個範圍時,會被切分到2個新的chunks中。當一個shard的資料過量時,chunks將會被遷移到其他的shards上。同樣,chunks也可以遷移到其他的shards上
Config Servers : Config伺服器儲存著叢集的metadata資訊,包括每個伺服器,每個shard的基本資料和chunk資訊Config伺服器主要儲存的是chunk資訊。每一個config伺服器都複製了完整的chunk資訊。
接著看一下要配置的測試環境資訊:
類比2個shard服務和一個config服務, 均運行在10.0.4.85機器上,只是連接埠不同
Shard1:27020
Shard2:27021
Config:27022
Mongos啟動時預設使用的27017連接埠
在C,D,E磁碟下分別建立如下檔案夾:
mongodb\bin
mongodb\db
然後用CMD命令列依次開啟相應檔案夾下的mongd檔案:
c:\mongodb\bin\mongod --dbpath c:\mongodb\db\ --port 27020
d:\mongodb\bin\mongod --dbpath d:\mongodb\db\ --port 27021
e:\mongodb\bin\mongod --configsvr --dbpath e:\mongodb\db\ --port 27022 (注:config設定管理員)
啟動mongos時,預設開啟了27017連接埠
e:\mongodb\bin\mongos --configdb 10.0.4.85:27022
然後開啟mongo:
E:\mongodb\bin>mongo 斷行符號 (有時加連接埠會造成下面的addshard命令出問題)
> use admin
switched to db admin
> db.runCommand( { addshard : "10.0.4.85:27020", allowLocal : 1, maxSize:2 , minKey:1, maxKey:10} )
--添加sharding,maxsize單位是M,此處設定比較小的數值只為示範sharding效果
{ "shardAdded" : "shard0000", "ok" : 1 }
> db.runCommand( { addshard : "10.0.4.85:27021", allowLocal : 1, minKey:1000} )
{ "shardAdded" : "shard0001", "ok" : 1 }
註:如果要移除sharding,可用下面寫法
db.runCommand( { removeshard : "localhost:10000" } );
> db.runCommand({listshards:1}); 查看shard節點列表
{
"shards" : [
{
"_id" : "shard0000",
"host" : "10.0.4.85:27020"
},
{
"_id" : "shard0001",
"host" : "10.0.4.85:27021"
}
],
"ok" : 1
}
接下來建立相應資料庫並設定其"可以sharding",建立自動切片的庫user001:
> config = connect("10.0.4.85:27022")
> config = config.getSisterDB("config")
> dnt_mongodb=db.getSisterDB("dnt_mongodb");
dnt_mongodb
> db.runCommand({enablesharding:"dnt_mongodb"})
{ "ok" : 1 } 註:一旦enable了個資料庫,mongos將會把資料庫裡的不同資料集放在不同的分區上。除非資料集被分區(下面會設定),否則一個資料集的所有資料將放在一個分區上。
> db.printShardingStatus();
--- Sharding Status ---
sharding version: { "_id" : 1, "version" : 3 }
shards:
{ "_id" : "shard0000", "host" : "10.0.4.85:27020" }
{ "_id" : "shard0001", "host" : "10.0.4.85:27021" }
databases:
{ "_id" : "admin", "partitioned" : false, "primary" : "config" }
{ "_id" : "dnt_mongodb", "partitioned" : true, "primary" : "shard0000" }
> db.runCommand( { shardcollection : "dnt_mongodb.posts1", key : {_id : 1}, unique: true } ) { "collectionsharded" : "dnt_mongodb.posts1", "ok" : 1 }
--使用shardcollection 命令分隔資料集,key自動產生 [必須為唯一索引unique index]。
如果要進行GridFS sharding,則需進行如下設定:
db.runCommand( { shardcollection : "dnt_mongodb.attach_gfstream.chunks", key : { files_id : 1 } } )
{"ok" : 1} ,更多內容參見http://eshilin.blog.163.com/blog/static/13288033020106215227346/
> db.printShardingStatus()
--- Sharding Status ---
sharding version: { "_id" : 1, "version" : 3 }
shards:
{ "_id" : "shard0000", "host" : "localhost:27020" }
{ "_id" : "shard0001", "host" : "localhost:27021" }
databases:
{ "_id" : "admin", "partitioned" : false, "primary" : "config" }
{ "_id" : "user001", "partitioned" : true, "primary" : "shard0000" }
dnt_mongodb.posts1e chunks:
{ "name" : { $minKey : 1 } } -->> { "name" : { $maxKey :
1 } } on : shard0000 { "t" : 1000, "i" : 0
下面我用一個工具來批量向dnt_mongodb資料庫的 posts1表中匯入資料,大約是16萬條資料。匯入處理程序中mongos會顯示類似如下資訊:
Tue Sep 07 12:13:15 [conn14] autosplitting dnt_mongodb.posts1 size: 47273960 shard: ns:dnt_mongodb.posts1 at: shard0000:10.0.4.85:27020 lastmod: 1|0 min: { _id: MinKey } max: { _id: MaxKey } on: { _id: 19 }(splitThreshold 47185920)
Tue Sep 07 12:13:15 [conn14] config change: { _id: "4_85-2010-09-07T04:13:15-0", server: "4_85", time: new Date(1283832795994), what: "split", ns: "dnt_mongodb.posts1", details: { before: { min: { _id: MinKey }, max: { _id: MaxKey } }, left: { min: { _id: MinKey }, max: { _id: 19 } }, right: { min: { _id: 19 }, max: {_id: MaxKey } } } }
Tue Sep 07 12:13:16 [conn14] moving chunk (auto): ns:dnt_mongodb.posts1 at: shard0000:10.0.4.85:27020 lastmod: 1|1 min: { _id: MinKey } max: { _id: 19 } to: shard0001:10.0.4.85:27021 #objects: 0
Tue Sep 07 12:13:16 [conn14] moving chunk ns: dnt_mongodb.posts1 moving ( ns:dnt_mongodb.posts1 at: shard0000:10.0.4.85:27020 lastmod: 1|1 min: { _id: MinKey }max: { _id: 19 }) shard0000:10.0.4.85:27020 -> shard0001:10.0.4.85:27021
Tue Sep 07 12:13:23 [WriteBackListener] ~ScopedDBConnection: _conn != null
Tue Sep 07 12:13:23 [WriteBackListener] ERROR: splitIfShould failed: ns: dnt_mongodb.posts1 findOne has stale config
Tue Sep 07 12:13:28 [WriteBackListener] autosplitting dnt_mongodb.posts1 size: 54106804 shard: ns:dnt_mongodb.posts1 at: shard0000:10.0.4.85:27020 lastmod: 2|1min: { _id: 19 } max: { _id: MaxKey } on: { _id: 71452 }(splitThreshold 47185920)
Tue Sep 07 12:13:28 [WriteBackListener] config change: { _id: "4_85-2010-09-07T04:13:28-1", server: "4_85", time: new Date(1283832808738), what: "split", ns: "dnt_mongodb.posts1", details: { before: { min: { _id: 19 }, max: { _id: MaxKey }}, left: { min: { _id: 19 }, max: { _id: 71452 } }, right: { min: { _id: 71452 }, max: { _id: MaxKey } } } }
在完成自動sharding之後,可以使用mongo看一下結果: > use dnt_mongodb
switched to db dnt_mongodb
> show collections
posts1
system.indexes
> db.posts1.stats(){
"sharded" : true,
"ns" : "dnt_mongodb.posts1",
"count" : 161531,
"size" : 195882316,
"avgObjSize" : 1212.6608267143768,
"storageSize" : 231467776,
"nindexes" : 1,
"nchunks" : 5,
"shards" : {
"shard0000" : {
"ns" : "dnt_mongodb.posts1",
"count" : 62434,
"size" : 54525632,
"avgObjSize" : 873.3323509626165,
"storageSize" : 65217024,
"numExtents" : 10,
"nindexes" : 1,
"lastExtentSize" : 17394176,
"paddingFactor" : 1,
"flags" : 1,
"totalIndexSize" : 2179072,
"indexSizes" : {
"_id_" : 2179072
},
"ok" : 1
},
"shard0001" : {
"ns" : "dnt_mongodb.posts1",
"count" : 99097,
"size" : 141356684,
"avgObjSize" : 1426.4476623913943,
"storageSize" : 166250752,
"numExtents" : 12,
"nindexes" : 1,
"lastExtentSize" : 37473024,
"paddingFactor" : 1,
"flags" : 1,
"totalIndexSize" : 3424256,
"indexSizes" : {
"_id_" : 3424256
},
"ok" : 1
}
},
"ok" : 1
}
通過上面的結果,可以出現16萬條記錄均分在了兩個sharding上,其中shard0000中有62434條,shard0001中有99097條。下面看一下這兩個sharding-chunk的分布情況(圖中的錯誤提示‘輸入字串格式不正確’主要因為運行環境與編譯器使用的環境不同,一個是64,一個是32位系統):
可以看到資料被按區間自動分割開了,有點像sqlserver的資料分區表,只不過這是自動完成的(目前我沒找到可以手工指定區間上下限的方式,如有知道的TX可以跟我說一下)。當然在本文中的測試中,共有5個chunk,其中4個位於shard0001,這種情況可以在每次測試過程中會發生變化,包括兩個sharding被分配的記錄數。另外就是在mongodb移動過程前後會在shard0000上產生一個檔案夾,裡麵包括一些bson檔案,名字形如(表格+日期等資訊):
post-cleanup.2010-09-07T04-13-31.1.bson
該檔案主要包括一些資料庫,表結構及相關記錄等資訊,我想應該是用於資料恢複備份啥的。
好的,今天的內容就先到這裡了。