標籤:
什麼是分區
分區是指將資料庫拆分,將其分散在不同的機器上的過程。將資料分散到不同的機器上,不需要功能強大的伺服器就可以儲存更多的資料和處理更大的負載。基本思想就是將集合切成小塊,這些塊分散到若干片裡,每個片只負責總資料的一部分,最後通過一個均衡器來對各個分區進行均衡。通過一個名為mongos的路由進程操作,mongos通過設定管理員知道資料和片的對應關係。大部分使用情境都是解決磁碟空間的問題,對於寫入有可能會變差,查詢則盡量避免跨分區查詢。
使用分區的時機:
1,機器的磁碟不夠用了。使用分區解決磁碟空間的問題。
2,單個mongod已經不能滿足寫資料的效能要求。通過分區讓寫壓力分散到各個分區上面,使用分區伺服器自身的資源。
3,想把大量資料放到記憶體裡提高效能。和上面一樣,通過分區使用分區伺服器自身的資源。
在搭建分區之前,先瞭解下分區中各個角色的作用。
① 設定管理員。是一個獨立的mongod進程,儲存叢集和分區的中繼資料,即各分區包含了哪些資料的資訊。最先開始建立,啟用日誌功能。像啟動普通的mongod一樣啟動設定管理員,指定configsvr選項。不需要太多的空間和資源,設定管理員的1KB空間相當於真實資料的200MB。儲存的只是資料的分布表。當服務不可用,則變成唯讀,無法分塊、遷移資料。
② 路由伺服器。即mongos,起到一個路由的功能,供程式串連。本身不儲存資料,在啟動時從設定管理員載入叢集資訊,開啟mongos進程需要知道設定管理員的地址,指定configdb選項。
③ 分區伺服器。是一個獨立普通的mongod進程,儲存資料資訊。可以是一個複本集也可以是單獨的一台伺服器。
1.建立檔案夾
data/config20 設定管理員configsvr 27020連接埠
data/shard17 分區伺服器 27017連接埠
data/shard18 分區伺服器 27018連接埠
2.啟動設定管理員
mongod --dbpath C:\Users\yuxl\Desktop\mongodb\data\config20 --port 27020
3. 建立mongos進程,以供應用程式串連
mongos --port 30000 --configdb 127.0.0.1:27020
4.啟動分區伺服器
mongod --dbpath C:\Users\yuxl\Desktop\mongodb\data\shard17 --port 27017
mongod --dbpath C:\Users\yuxl\Desktop\mongodb\data\shard18 --port 27018
5.添加分區
串連mongos進程mongo 127.0.0.1:30000/admin
添加分區
sh.addShard("127.0.0.1:27017")
sh.addShard("127.0.0.1:27018")
查看狀態sh.status(),我們發現兩個分區
shards:
{ "_id" : "shard0000", "host" : "127.0.0.1:27017" }
{ "_id" : "shard0001", "host" : "127.0.0.1:27018" }
6.添加待分區的庫
sh.enableSharding(databaseName);
sh.enableSharding(“shop”);
7: 添加待分區的表
sh.shardCollection(‘dbName.collectionName’,{field:1});
field是collection的一個欄位,系統將會利用filed的值,來計算應該分到哪一個片上.
這個filed叫”片鍵”, shard key
sh.shardCollection(“shop.goods”,{goodsid:1});
接下來插入資料進行測試,為了便於查看效果,使用一下操作
use config
db.settings.update({"_id":"chunksize"},{$set:{"value":1}})
use shop
for(var i=1;i<=10000;i++)
{
db.goods.insert({“goodsid”:i,”goodsname”:”abddsdfsdfsdfsdfsddddddddddddd”})
}
然後我們分別串連兩個分區伺服器上發現都有資料,但是不是很均勻
原因:
mongodb不是從單篇文檔的層級,絕對平均的散落在各個片上, 而是N篇文檔,形成一個塊"chunk",優先放在某個片上, 當這片上的chunk,比另一個片的chunk,區別比較大時, (>=3) ,會把本片上的chunk,移到另一個片上, 以chunk為單位,維護片之間的資料均衡
問: 為什麼插入了10萬條資料,才2個chunk?
答: 說明chunk比較大(預設是64M)
在config資料庫中,修改chunksize的值.
問: 既然優先往某個片上插入,當chunk失衡時,再移動chunk,
自然,隨著資料的增多,shard的執行個體之間,有chunk來回移動的現象,這將帶來什麼問題?
答: 伺服器之間IO的增加,
問: 能否我定義一個規則, 某N條資料形成1個塊,預告分配M個chunk,
M個chunk預告分配在不同片上.
以後的資料直接入各自預分配好的chunk,不再來回移動?
答: 能, 手動預先分區! 注意: 預先分區的collection得是空的
以shop.user表為例
1: sh.shardCollection(‘shop.user’,{userid:1}); //user表用userid做shard key
2: for(var i=1;i<=40;i++) { sh.splitAt(‘shop.user‘,{userid:i*1000}) } // 預先在1K 2K...40K這樣的界限切好chunk(雖然chunk是空的), 這些chunk將會均勻移動到各片上.
3: 通過mongos添加user資料. 資料會添加到預先分配好的chunk上, chunk就不會來回移動了.
在產生環境中我們使用replcation set與shard分區結合使用
1:在3台獨立伺服器上,分別運行 27017,27018,27019執行個體, 互為複本集,形成3套repl set
2: 在3台伺服器上,各配置config server, 運行27020連接埠上
3: 配置mongos
./bin/mongos --port 30000 \
--dbconfig 192.168.1.201:27020,192.168.1.202:27020,192.168.1.203:27020
4:連線路由器
./bin/mongo --port 30000
5: 添加repl set為片
>sh.addShard(‘192.168.1.201:27017’);
>sh.addShard(‘192.168.1.202:27017’);
>sh.addShard(‘192.168.1.203:27017’);
6: 添加待分區的庫
>sh.enableSharding(databaseName);
7: 添加待分區的表
>sh.shardCollection(‘dbName.collectionName’,{field:1});
MongoDB的分區(9)