一:分區介紹
這是一種將海量的資料水平擴充的資料庫叢集系統,資料分表格儲存體在sharding的各個節點上,使用者通過簡單的配置就可以很方便地構建一個分布式MongoDB叢集。
MongoDB 的資料分塊稱為 chunk。每個 chunk 都是 Collection 中一段連續的資料記錄,通常最大尺寸是 200MB,超出則產生新的資料區塊。
要構建一個 MongoDB Sharding Cluster,需要三種角色:
Shard Server
即儲存實際資料的分區,每個Shard可以是一個mongod執行個體,也可以是一組mongod執行個體構成的Replica Set。為了實現每個Shard內部的auto-failover,MongoDB官方建議每個Shard為一組Replica Set。
Config Server
為了將一個特定的collection儲存在多個shard中,需要為該collection指定一個shard key,例如{age: 1} ,shard key可以決定該條記錄屬於哪個chunk。Config Servers就是用來儲存:所有shard節點的配置資訊、每個chunk的shard key範圍、chunk在各shard的分布情況、該叢集中所有DB和collection的sharding配置資訊。
Route Process
這是一個前端路由,用戶端由此接入,然後詢問Config Servers需要到哪個Shard上查詢或儲存記錄,再串連相應的Shard進行操作,最後將結果返回給用戶端。用戶端只需要將原本發給mongod的查詢或更新要求原封不動地發給Routing Process,而不必關心所操作的記錄儲存在哪個Shard上。
下面我們在同一台物理機器上構建一個簡單的 Sharding Cluster:
架構圖如下:
二:實驗環境
在同一台機器上類比一個設定管理員,一個mongos伺服器,2個分區(每個分區是單一實例)
三:實驗步驟
3.1 下載解壓Mongodb
理應在每台伺服器上都下載解壓mongodb.由於這裡都在同一台機器上類比操作,故只需解壓一次。
tar -xvf mongodb-linux-x86_64-2.6.9.tgz
# 為了方便管理,把安裝檔案移動到 / data 下
[root@pc download]# mv mongodb-linux-x86_64-2.6.9 /data/mongodb
3.2 建立相關目錄
為mongodb建立資料庫存放的位置和記錄檔
[root@pc mongodb]# cd /data/mongodb/[root@pc mongodb]# mkdir data[root@pc mongodb]# touch logs[root@pc mongodb]# ls -ltrtotal 68-rw-r--r-- 1 1046 1046 1359 Mar 23 22:49 README-rw-r--r-- 1 1046 1046 34520 Mar 23 22:49 GNU-AGPL-3.0-rw-r--r-- 1 1046 1046 17793 Mar 23 22:49 THIRD-PARTY-NOTICESdrwxr-xr-x 2 root root 4096 Jul 15 13:26 bindrwxr-xr-x 2 root root 4096 Jul 15 13:34 data-rw-r--r-- 1 root root 0 Jul 15 13:34 logs #建配置資訊服務器資料檔案目錄[root@pc download]# mkdir -p /dbs/config #建分區目錄mkdir -p /dbs/shard1mkdir -p /dbs/shard2 #建日誌目錄mkdir /logs #建記錄檔touch /logs/config.log touch mongos.log touch shard1.log touch shard2.log
3.3 配置PATH
[root@pc dbs]# vi /root/.bash_profile
在PATH行末尾添加:
:/data/mongodb/bin
[root@pc dbs]# source /root/.bash_profile
3.4 啟動設定管理員
設定管理員需要最先啟動,mongos伺服器需要用到上面的配置資訊。設定管理員的啟動就像普通mongod一樣。
設定管理員不需要很多空間和資源(200MB實際資料大約佔1KB的配置空間)
[root@pc dbs]# mongod --dbpath=/dbs/config --logpath=/logs/config.log --fork --port 1000
about to fork child process, waiting until server is ready for connections.
forked process: 5055
child process started successfully, parent exiting
[root@pc ~]# ps -ef | grep mongo
root 9691 1 3 22:31 ? 00:00:00 mongod --dbpath=/dbs/config --logpath=/logs/config.log --fork --port 1000
3.5 啟動mongos伺服器
[root@pc ~]# mongos --port 1001 --logpath=/logs/mongos.log --configdb=192.168.6.51:1000 --fork2015-07-16T22:32:36.776-0700 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: 9716child process started successfully, parent exiting
--configdb這裡記錄的是設定管理員所在IP和連接埠號碼。
配置--conigdb的時候ip地址不能填localhost或127.0.0.1否則添加分區時會返回如下錯誤資訊:
1. {2. "ok" : 0,3. "errmsg" : "can't use localhost as a shard since all shards need to communicate. either use all shards and configdbs in localhost or all in actual IPs host: 192.168.6.51:1000 isLocalHost:0"4. }
3.6 啟動分區
#分區1
[root@pc ~]# mongod --dbpath=/dbs/shard1 --logpath=/logs/shard1.log --fork --port 1002
about to fork child process, waiting until server is ready for connections.
forked process: 10583
child process started successfully, parent exiting
#分區2
[root@pc ~]# mongod --dbpath=/dbs/shard2 --logpath=/logs/shard2.log --fork --port 1003
about to fork child process, waiting until server is ready for connections.
forked process: 10659
child process started successfully, parent exiting
3.7 添加分區
#注意:添加分區和切分資料都是在mongos伺服器上進行操作的。
登入mongos伺服器,
[root@pc mongodb]# mongo localhost:1001/admin
MongoDB shell version: 2.6.9
connecting to: localhost:1001/admin
#添加分區
mongos> db.runCommand({addshard:"localhost:1002",allowLocal:true });
{ "shardAdded" : "shard0000", "ok" : 1 }
mongos> db.runCommand({addshard:"localhost:1003",allowLocal:true });
{ "shardAdded" : "shard0001", "ok" : 1 }
#查看所有的片
mongos> use config;
switched to db config
mongos> db.shards.find();
{ "_id" : "shard0000", "host" : "localhost:1002" }
{ "_id" : "shard0001", "host" : "localhost:1003" }
3.8 切分資料
預設的是不會將儲存的每條資料進行分區處理,需要在資料庫和集合的粒度上都開啟分區功能。
這裡以dba.b為例
mongos> use dba;
switched to db dba
mongos> db.createCollection("b");
{ "ok" : 1 }
3.8.1 開啟庫的分區功能
mongos> use admin;
switched to db admin
mongos> db.runCommand({"enablesharding":"dba"});
{ "ok" : 1 }
3.8.2 開啟表的分區功能
mongos> db.runCommand({"shardcollection":"dba.b","key":{"id":1}}){ "collectionsharded" : "dba.b", "ok" : 1 }注意:需要切換到admin庫執行命令。片鍵:上面的key就是所謂的片鍵(shard key)。MongoDB不允許插入沒有片鍵的文檔。但是允許不同文檔的片鍵類型不一樣,MongoDB內部對不同類型有一個排序: mongos> use config;switched to db configmongos> db.databases.find();{ "_id" : "admin", "partitioned" : false, "primary" : "config" }{ "_id" : "dba", "partitioned" : true, "primary" : "shard0000" } 可以看到dba這個庫分區了。 mongos> db.chunks.find();{ "_id" : "dba.b-id_MinKey", "lastmod" : Timestamp(1, 0), "lastmodEpoch" : ObjectId("55a8c850fe175819f8525593"), "ns" : "dba.b", "min" : { "id" : { "$minKey" : 1 } }, "max" : { "id" : { "$maxKey" : 1 } }, "shard" : "shard0000" } Chunks:理解MongoDB分區機制的關鍵是理解Chunks。mongodb不是一個分區上儲存一個區間,而是每個分區包含多個區間,這每個區間就是一個塊。
3.9 分區測試
mongos> use dba;switched to db dbamongos> for(i=0;i<100000;i++){ db.b.insert({"id":i,"Name":"baidandan","Date":new Date()}); }WriteResult({ "nInserted" : 1 }) mongos> use config;switched to db configmongos> db.chunks.find();{ "_id" : "dba.b-id_MinKey", "lastmod" : Timestamp(2, 1), "lastmodEpoch" : ObjectId("55a8c850fe175819f8525593"), "ns" : "dba.b", "min" : { "id" : { "$minKey" : 1 } }, "max" : { "id" : 0 }, "shard" : "shard0000" }{ "_id" : "dba.b-id_0.0", "lastmod" : Timestamp(1, 3), "lastmodEpoch" : ObjectId("55a8c850fe175819f8525593"), "ns" : "dba.b", "min" : { "id" : 0 }, "max" : { "id" : 5562 }, "shard" : "shard0000" }{ "_id" : "dba.b-id_5562.0", "lastmod" : Timestamp(2, 0), "lastmodEpoch" : ObjectId("55a8c850fe175819f8525593"), "ns" : "dba.b", "min" : { "id" : 5562 }, "max" : { "id" : { "$maxKey" : 1 } }, "shard" : "shard0001" }
我們可以看到現在有三個塊:(-∞,0)在shard0000上,[0,5562)在shard0000上和[5562,+ ∞)在shard0001上。
資料已經被自動分配到了這兩個片上面。
Note:通過sh.status()可以很直觀的查看當前整個叢集的分區情況,類似如下:
mongos> sh.status();--- Sharding Status --- sharding version: {"_id" : 1,"version" : 4,"minCompatibleVersion" : 4,"currentVersion" : 5,"clusterId" : ObjectId("55a89388fe175819f8524cc2")} shards:{ "_id" : "shard0000", "host" : "localhost:1002" }{ "_id" : "shard0001", "host" : "localhost:1003" } databases:{ "_id" : "admin", "partitioned" : false, "primary" : "config" }{ "_id" : "dba", "partitioned" : true, "primary" : "shard0000" }dba.bshard key: { "id" : 1 }chunks:shard00002shard00011{ "id" : { "$minKey" : 1 } } -->> { "id" : 0 } on : shard0000 Timestamp(2, 1) { "id" : 0 } -->> { "id" : 5562 } on : shard0000 Timestamp(1, 3) { "id" : 5562 } -->> { "id" : { "$maxKey" : 1 } } on : shard0001 Timestamp(2, 0)
在分區伺服器上查看下資料
--分區1[root@pc config]# mongo localhost:1002/adminMongoDB shell version: 2.6.9connecting to: localhost:1002/admin> show dbs;admin (empty)dba 0.078GBlocal 0.078GB> use dba;switched to db dba> db.b.find().count();5562 --分區2[root@pc ~]# mongo localhost:1003MongoDB shell version: 2.6.9connecting to: localhost:1003/test> show dbs;admin (empty)dba 0.078GBlocal 0.078GB> use dba;switched to db dba> show tables;bsystem.indexes> db.b.find().count();94438
--本篇文章參考自:搭建mongodb分區,MongoDB分區實戰(二):Sharding,Mongodb權威指南。