MongoDB 分區Sharding 方案 及 chunks塊 和 片鍵分析

來源:互聯網
上載者:User
--------------------------------------------------------------------------------

0,建立3個Shard Server//建立資料庫,記錄檔[root@localhost ~]# mkdir -p /data/shard/s0[root@localhost ~]# mkdir -p /data/shard/s1[root@localhost ~]# mkdir -p /data/shard/s2[root@localhost ~]# mkdir -p /data/shard/logShard Sever 1 : 38010Shard Sever 2 : 38011Shard Sever 3 : 38012Config Server : 40000Route Process : 500001,建立3個資料庫作為3個分區這是裡為方便看日誌,直接在命令列輸出查看/Apps/mongo/bin/mongod --dbpath=/data/shard/s0 --shardsvr --port 38010 --directoryperdb --rest/Apps/mongo/bin/mongod --dbpath=/data/shard/s1 --shardsvr --port 38011 --directoryperdb --rest/Apps/mongo/bin/mongod --dbpath=/data/shard/s2 --shardsvr --port 38012 --directoryperdb --rest(--directoryperdb那你每個庫的檔案會單獨放在一個檔案夾裡)正式運行要後台運行就用下面的:/Apps/mongo/bin/mongod --dbpath=/data/shard/s0 --shardsvr --port 38010 --directoryperdb --logpath=/data/shard/log/s0.log --logappend --fork --rest/Apps/mongo/bin/mongod --dbpath=/data/shard/s1 --shardsvr --port 38011 --directoryperdb --logpath=/data/shard/log/s1.log --logappend --fork --rest/Apps/mongo/bin/mongod --dbpath=/data/shard/s2 --shardsvr --port 38012 --directoryperdb --logpath=/data/shard/log/s2.log --logappend --fork --rest--------------------------------------------------------------------------------1,啟動Config Server, Config Server : 40000//建立資料庫,記錄檔mkdir -p /data/shard/config/Apps/mongo/bin/mongod --dbpath /data/shard/config --configsvr --port 40000 --directoryperdb --rest正式運行要後台運行就用下面的:/Apps/mongo/bin/mongod  --dbpath /data/shard/config --configsvr --port 40000  --logpath=/data/shard/log/config.log --fork --directoryperdb --rest--------------------------------------------------------------------------------2,啟動Route Process,Route Process : 50000/Apps/mongo/bin/mongos --port 50000 --configdb 127.0.0.1:40000 --chunkSize 1 --chunkSize 1 (MB)指定分區的最小單位容量,這裡設定1M,方便查看效果 正式運行要後台運行就用下面的:/Apps/mongo/bin/mongos --port 50000 --configdb 127.0.0.1:40000 --chunkSize 50 --logpath=/data/shard/log/route.log --fork--------------------------------------------------------------------------------:此時並未加入任何片到Sharding叢集中,可以看到,對於Sharding叢集中,其admin資料庫是不分區的方式存放在Config Server中的!-----------------------------------------------------------------------------------3,串連到mongos配置Sharding用Mongo Shell 登入 Route Process/Apps/mongo/bin/mongo --port 50000 use admin (記得執行這一點,切換到admin資料庫)//添加分區節點,每個分區都是一個複本集db.runCommand({addshard:"127.0.0.1:38010",allowLocal:true})db.runCommand({addshard:"127.0.0.1:38011",allowLocal:true})db.runCommand({addshard:"127.0.0.1:38012",allowLocal:true})

allowLocal:true僅僅開發時才將分區配置到本地,生產時不能這樣-----------------------------------------------------------------------------------:配置資訊被添加到Config Server的config資料庫的shards集合中:-------------------------------------------------------------------------------4,設定資料庫mydb,啟用分區
use admindb.runCommand({enablesharding:"mydb"}): mydb啟用分區後,其基片(primary shard server)是shard0000mydb被配置成啟用分區後,配置資訊是存放在設定管理員的資料庫config的databases集合裡!-------------------------------------------------------------------------------5,設定要分區的集合:使集合users以片鍵_id來分區
db.runCommand({shardcollection:"mydb.users",key:{_id:1}})mydb的users集合被配置成啟用分區後,配置資訊是存放在設定管理員的資料庫config的collections集合裡!

--------------------------------------------------------------------------------這裡可以看到,路由伺服器是不會存放配置資訊(不用配置dbpath也是這個原因,但會緩衝設定管理員上的配置!)--------------------------------------------------------------------------------6,Sharding Cluster的資料插入的測試(遞增片鍵方式)use admindb.runCommand({shardcollection:"mydb.users",key:{_id:1}})use mydb測試插入60萬條資料for(var i=1; i<=600000; i++) db.users.insert({age:i,name:"mary",addr:"guangzhou",country:"China"})然後等幾分鐘,集合users的資料就均勻分布到各個分區,分區完成1,先看看每個trunk,這裡測試需要,設定了1MB/trunk,每個trunk記錄了片鍵的範圍,還有所在的片的名稱圖:已插入21萬個文檔,主要在shard0002插入圖:已插入28萬個文檔,之後到主要向shard0001插入圖:已插入40萬個文檔,之後到主要向shard0002插入圖:已插入61萬個文檔?,主要向shard0000插入圖:60萬個文檔全部正常插入完成,此時資料不太均勻以上都是5分鐘以內的分區情況,過了幾小時後,每個Shard Server的chunks塊數量是相同的,證明mongos路由伺服器會即時對各分區進行負載平衡!因為Sharding key 是ObjectId這裡ObjectId就像一個遞增片鍵,插入時不能均勻地路由到各片,此時寫入的負載不均勻,這裡60萬個文檔寫入完後在各片分布不太均勻,所以mongos路由會在後台對各片進行負載平衡,直至各片的chunks塊數量相等!---------------------------------------------------------------------------------------------B:向已有42個塊且有資料的Sharding Cluster插入60萬條遞增鍵的文檔:以上是3分鐘之內的,剛剛到60萬條插入完畢的時刻!以下是10分鐘穩定後:剛開始插入的37萬條主要集中在shard0001上,然後分別有18萬條和5萬條插入到shard0002和shard0000,時間上插入得不太均勻!因為這是遞增鍵,操作往往會集中在某個塊和某個片上!
--------------------------------------------------------------------------------7,Sharding Cluster的資料插入的測試(隨機片鍵方式)use admindb.runCommand({shardcollection:"mydb.peoples",key:{ram:1}})  

use mydb測試插入60萬條資料for(var i=1; i<=600000; i++) db.peoples.insert({name:"irelandken__ZHEN",age:i,addr:"guangzhou",country:"China", ram : Math.random()})這裡我們有一個隨機小數[0--1)來作為片鍵,3分鐘後:非常不均勻!15分鐘後:均勻了!怎麼用隨機片鍵還是會出現這種情況呢??剛插入資料還是分布得那麼不均勻!因為剛開始裡,設定管理員裡沒有chunks塊,第一個無限大的塊位於基片上,而後來邊向資料庫插入資料邊分裂出更細的chunks塊,這時分裂出的塊主要分布在基片shard000上所以導致插入操作集中在基片上執行!那現在已經有83個chunks的情況下再插入60萬條呢?覺得這次一定會很均勻再插入60萬條資料for(var i=1; i<=600000; i++) db.peoples.insert({name:"ZHEN",age:i,addr:"zhuhai",country:"China", ram : Math.random()})60萬個文檔剛插入完成的情況:看,猜對了,終於看到了隨機片鍵的效果!!因為3個分區上的chunks塊是均勻的,因為再產生的60萬個文檔的片鍵也是隨機鍵將會均勻地命中3個片的chunks!   mongos路由伺服器的想法應該是如果分區上的負載不均衡,就會調整各分區,直至各分區的chunks塊數量大致相等!
現在,我們將這個集合清空,再次測試插入60萬條隨機鍵的文檔use mydbdb.peoples.remove()清空這個集合(只要不刪除這個集合)是不會刪除已經存在的153個chunks塊的!向已有153個chunks塊的空集合插入60萬個隨機鍵的文檔for(var i=1; i<=600000; i++) db.peoples.insert({name:"jack",age:i,addr:"Beijing",country:"China", ram : Math.random()})

可見,整個插入過程是相當均勻!而塊的數量僅僅增加了2塊,就是說60萬個文檔幾乎全部"命中"已存在的各個塊!-------------------------------------------------------------------------------------------8,測試6和7的小結
1:如果剛開始對於新的集合,設定管理員裡沒有該集合的chunks塊資訊,這裡無論是遞增鍵或隨機鍵,  資料的插入過程也不會均勻,甚至有可能集中在某台機器上,然後mongos再來執行負載平衡
2: mongos路由會在後台對各片進行負載平衡,直至各片的chunks塊數量相等!
3: 對於負載平衡的Sharding Cluster(各片的chunks塊數量相等),對於隨機鍵的操作會非常有效,基本整個過程是很均勻的    而此時遞增鍵的操作還是會出現嚴重的負載不均衡的情況!
--------------------------------------------------------------------------------6,移除Shard Server,回收資料db.runCommand({"removeshard" : "127.0.0.1:38010"})因為127.0.0.1:38010是資料庫test和mydb的Primary片"primary" : "shard0000"基片,所以要手動移動資料庫的基片如:/* 1 */{  "_id" : "test",  "partitioned" : true,  "primary" : "shard0000"}/* 2 */{  "_id" : "mydb",  "partitioned" : true,  "primary" : "shard0000"}手動修改資料庫test的基片,改為127.0.0.1:38011執行: mongos> db.runCommand({"moveprimary" : "test","to" : "127.0.0.1:38011"}){ "primary " : "shard0001:127.0.0.1:38011", "ok" : 1 }手動修改資料庫test的基片,改為127.0.0.1:38011執行: mongos> db.runCommand({"moveprimary" : "mydb","to" : "127.0.0.1:38011"}){ "primary " : "shard0001:127.0.0.1:38011", "ok" : 1 }依賴要刪除的片的關係全部刪除後,再找執行一次:db.runCommand({"removeshard" : "127.0.0.1:38010"})mongos> db.runCommand({"removeshard" : "127.0.0.1:38010"}){        "msg" : "removeshard completed successfully",        "state" : "completed",        "shard" : "shard0000",        "ok" : 1}mongos分回收該片的資料,平均到其它片,然後在分區叢集中移除該片!多次調用這一句,中間可以看到進行的進度!此操作對使用者完全透明,不需要停機操作!--------------------------------------------------------------------------------7,新增Shard Server串連到mongos因為在各分區裡存在資料庫test和mydb的集合的分區,而規定加入的新mongod不能含有相同的資料庫(試想如果加入的資料庫含有資料庫mydb,且其中含有一定數量的資料,此資料一定要被刪除)向mongos新加入的Shard Server一定不能含有與其它片相同的資料庫的!use admindb.runCommand({addshard:"127.0.0.1:38010",allowLocal:true})新的片被加入後,mongos再次將次執行負載平衡,將資料均勻到各片中!--------------------------------------------------------------------------------從各部分的LOG來看,只有節點Shard Server和路由Route Process是比較"忙"的,Config Server好像僅僅只是同步Route Process的配置而已,因為路由Route Process不會持久化資料,Config Server為它存放配置感覺路由Route Process是一個Facade,外部看來是一個資料庫

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.