0.5372018.04.22 21:20:07字數 4283閱讀 4842html
分片在多臺服務器上分佈數據的方法, Mongodb使用分片來支持具備很是大的數據集和高吞吐量的操做的部署mongodb
具備大數據集和高吞吐量應用程序的數據庫系統,能夠挑戰單臺服務器的容量。
例如,高查詢率能夠耗盡服務器的cpu容量,工做集大小大於系統的RAM強制磁盤驅動器的I/O容量,shell
有兩種方法來解決系統增加:垂直和水平縮放。數據庫
垂直縮放 涉及增長的單個服務器的容量,例如使用更強大的CPU,加入更多的RAM,或增長的存儲空間量。可用技術中的限制可能限制單個機器對於給定工做負載足夠強大。此外,基於雲的提供商具備基於可用硬件配置的硬上限。所以,對於垂直縮放存在實際的最大值。編程
包括將系統數據和負載在多個服務器,添加額外的服務器,須要增長容量。雖然單個機器的總速度或容量可能不高,可是每一個機器處理整個工做負載的子集,潛在地提供比單個高速大容量服務器更好的效率。擴展部署的容量僅須要根據須要添加額外的服務器,這能夠是比單個機器的高端硬件低的整體成本。權衡是基礎設施的複雜性和部署的維護。vim
Mongodb的支持水平擴展,分片。緩存
一、分片目的安全
對於單臺數據庫服務器,龐大的數據量及高吞吐量的應用程序對它而言無疑是個巨大的挑戰。頻繁的CRUD操做可以耗盡服務器的CPU資源,快速的數據增加也會讓硬盤存儲無能爲力,最終內存沒法知足數據須要致使大量的I/O,主機負載嚴重。爲了解決這種問題,對於數據庫系統通常有兩種方法:垂直擴展和分片(水平擴展)。bash
【垂直擴展】:添加更多的CPU和存儲資源來增長系統性能。這種方式缺點是:擁有大量CPU和RAM資源的高端機器比普通PC機器昂貴得太多,並且單點故障會影響整個系統的服務。服務器
【分片】:相反地,分片將大的數據集分配到多臺主機上,每一個分片是一個獨立的數據庫,這些分片總體上構成一個完整的邏輯數據庫。分片減小了每臺服務器上的數據操做量,隨着集羣的增加,每臺分片處理愈來愈少的數據,結果,增長了系統總體服務能力。另外,分片還減小了每臺服務器須要存儲的數據量。
二、MongoDB中的分片
MongoDB經過配置分片集羣來支持分片,一個分片集羣包括如下幾個組件:分片,查詢路由,配置服務器
數據劃分
MongoDB的數據劃分,是以集合級別爲標準。分片經過shard key來劃分集合數據。
爲了對集合分片,你須要指定一個shard key。shard key既能夠是集合的每一個文檔的索引字段也能夠是集合中每一個文檔都有的組合索引字段。MongoDB將shard keys值按照塊(chunks)劃分,而且均勻的將這些chunks分配到各個分片上。MongoDB使用基於範圍劃分或基於散列劃分來劃分chunks的。
MongoDB經過shard key值將數據集劃分到不一樣的範圍就稱爲基於範圍劃分。對於數值型的shard key:你能夠虛構一條從負無窮到正無窮的直線(理解爲x軸),每一個shard key 值都落在這條直線的某個點上,而後MongoDB把這條線劃分爲許多更小的沒有重複的範圍成爲塊(chunks),一個chunk就是就某些最小值到最大值的範圍。
MongoDB計算每一個字段的hash值,而後用這些hash值創建chunks。
基於範圍劃分對於範圍查詢比較高效。假設在shard key上進行範圍查詢,查詢路由很容易可以知道哪些塊與這個範圍重疊,而後把相關查詢按照這個路線發送到僅僅包含這些chunks的分片。可是基於範圍劃分很容易致使數據不均勻分佈,這樣會削弱分片集羣的功能。例如當shard key是個成直線上升的字段,如時間。那麼,全部在給定時間範圍內的請求都會映射到相同的chunk,也就是相同的分片上。這種狀況下,小部分的分片將會承受大多數的請求,那麼系統總體擴展並不理想。
相反的,基於散列劃分是以犧牲高效範圍查詢爲代價,它可以均勻的分佈數據,散列值可以保證數據隨機分佈到各個分片上。
MongoDB容許DBA們經過標籤標記分片的方式直接平衡數據分佈策略,DBA能夠建立標籤而且將它們與shard key值的範圍進行關聯,而後分配這些標籤到各個分片上,最終平衡器轉移帶有標籤標記的數據到對應的分片上,確保集羣老是按標籤描述的那樣進行數據分佈。標籤是控制平衡器行爲及集羣中塊分佈的主要方法
四、維持數據分佈平衡
新加入的數據及服務器都會致使集羣數據分佈不平衡,MongoDB採用兩種方式確保數據分佈的平衡:
拆分是一個後臺進程,防止塊變得太大。當一個塊增加到指定塊大小的時候,拆分進程就會塊一分爲二,整個拆分過程是高效的。不會涉及到數據的遷移等操做。
平衡器是一個後臺進程,管理塊的遷移。平衡器可以運行在集羣任何的mongd實例上。當集羣中數據分佈不均勻時,平衡器就會將某個分片中比較多的塊遷移到擁有塊較少的分片中,直到數據分片平衡爲止。舉個例子:若是集合users有100個塊在分片1裏,50個塊在分片2中,那麼平衡器就會將分片1中的塊遷移到分片2中,直到維持平衡。
分片採用後臺操做的方式管理着源分片和目標分片之間塊的遷移。在遷移的過程當中,源分片中的塊會將全部文檔發送到目標分片中,而後目標分片會獲取並應用這些變化。最後,更新配置服務器上關於塊位置元數據。
添加新分片到集羣中會產生數據不平衡,由於新分片中沒有塊,當MongoDB開始遷移數據到新分片中時,等到數據分片平衡恐怕須要點時間。
當刪除一個分片時,平衡器將會把分片中全部塊遷移到另外一個分片中,在完成這些遷移並更新元數據後,你就能夠安全的刪除分片了。
一個mongodb分片集羣由如下幾部分組成
12.jpg
shard
每一個shard包含分片數據的子集,每一個shard能夠部署一個副本集13.jpg
mongos
MongoS充當一個查詢的路由器,提供客戶端應用程序和所述分片簇之間的接口,mongos做爲數據庫集羣請求的入口,全部的請求都是經過mongos來進行協調的,不須要在應用程序添加一個路由選擇器,mongos本身就是一個請求分發中心,它負責把對應的數據請求轉發到對應的shard服務器上,在生產環境中一般有多個monogs做爲請求的入口,防止其中一個掛掉全部mongos請求都沒有辦法操做config servers
爲集羣配置的服務器存儲元數據和配置設置,從Mongodb3.4開始,配置服務器必須部署爲複製集,mongos自己沒有物理存儲分片服務器和數據路由信息,只是緩存在內存當中,配置服務器則實際存儲這些數據,mongos第一次啓動或者關掉重啓會從configserver中加載配置信息,之後若是配置信息有變化會經過全部的mongos更新本身的狀態,這樣mongs就能繼續準確路由,在生產環境中一般有多個config server配置服務器,由於它存儲了分片路由的元數據,若是就一個若是掛掉一個,整個mongodb基礎就會掛掉。片鍵
片鍵
一、在分發集合中文件時,mongodb的分區使用的收集片鍵關鍵,在片鍵由存在目標集合中的每一個文檔中的一個不可變或多個字段
二、在分割集合的時候選擇片鍵,<font color=red size=4>分片鍵完成以後是不能更改的</font>,分片集合只能有1個片鍵,到片鍵的非空集合,集合必須有一個索引,與片鍵啓動,對於空空集合,若是集合還沒有具備指定分片鍵的相關索引,則Mongodb會建立索引
三、分片鍵的選擇會影響分片集羣的性能和效率以及可伸縮性,具備最佳可能的硬件能夠經過分片達到瓶頸,片鍵和其支持指數的選擇也能夠影響數據的拆分,但集羣可使用
四、片鍵決定了集羣中一個集合的文件咋不一樣的片鍵中的分佈,片鍵字段必須被索引,且在集合中的每條記錄都不能爲空,能夠是單個字段或者是複合字段
五、Mongodb使用片鍵的範圍是吧數據分佈在分片中,每一個範圍,又稱爲數據塊,定義了一個不重疊的片鍵範圍Mongodb把數據塊與他們存儲的文檔分佈到集羣中的不一樣分佈中,當一個數據塊的大小超過數據塊最大大小的時候,Mongodb會宜聚片鍵的範圍將數據塊分裂爲更小的數據塊
14.png
sh.shardCollection()
sh.shardCollection(namespace, key)
二、哈希片鍵使用單字段的哈希索引進行數據在分片之間的平均分發,除數取餘
和一致性哈希
三、被選爲片鍵的字段必須有足夠大的基數,或者有足夠多的不一樣的值,對於單調的遞增的字段若是ObjectID
或是時間戳,哈希索引效果更好
四、若是在一個空集合建立哈希片鍵,Mongodb會自動建立並遷移數據塊,以保證每一個分片上都有兩個數據塊,也能夠執行shardCollection
指定numInitialChunks
參數以控制初始化時Mongodb建立數據塊數目,或者手動調用split
命令在分片上分裂數據塊
五、對使用了哈希片鍵分片的集合進行請求時,Mongodb會自動計算哈希值,應用不須要解析哈希值
配置config server 副本集
[root@My-Dev db2]# vim config1.conf [root@My-Dev db1]# vim configsvr.conf logpath=/home/mongodb/test/db1/log/db1.log pidfilepath=/home/mongodb/test/db1/db1.pid logappend=true port=30000 fork=true dbpath=/home/mongodb/test/db1/data configsvr=true # 在配置文件添加此項就行 oplogSize=512 replSet=config
[root@My-Dev db2]# vim config2.conf logpath=/home/mongodb/test/db2/log/db2.log pidfilepath=/home/mongodb/test/db2/db2.pid logappend=true port=30001 fork=true dbpath=/home/mongodb/test/db2/data oplogSize=512 replSet=config configsvr=true
[root@My-Dev db2]# vim config3.conf logpath=/home/mongodb/test/db3/log/db3.log pidfilepath=/home/mongodb/test/db3/db3.pid logappend=true port=30002 fork=true dbpath=/home/mongodb/test/db3/data oplogSize=512 replSet=config configsvr=true
[root@My-Dev bin]# ./mongod -f /home/mongodb/test/db1/config1.conf about to fork child process, waiting until server is ready for connections. forked process: 5260 child process started successfully, parent exiting [root@My-Dev bin]# ./mongod -f /home/mongodb/test/db2/config2.conf about to fork child process, waiting until server is ready for connections. forked process: 5202 child process started successfully, parent exiting [root@My-Dev bin]# ./mongod -f /home/mongodb/test/db3/config3.conf about to fork child process, waiting until server is ready for connections. forked process: 4260 child process started successfully, parent exiting
> use admin switched to db admin > config = { _id:"config",members:[ {_id:0,host:"conf1:30000"}, {_id:1,host:"conf2:30001"}, {_id:2,host:"conf3:30002"}] } #定義副本集 { "_id" : "config", "members" : [ { "_id" : 0, "host" : "conf1:30000" }, { "_id" : 1, "host" : "conf2:30001" }, { "_id" : 2, "host" : "conf3:30002" } ] } > rs.initiate(config) #初始化副本集 { "ok" : 1 }
配置mongos
config server
必須是複製集才行,結果個人版本是3.4最新的版本,因此說還須要添加兩臺confi server
[root@My-Dev db4]# vim mongos.conf logpath=/home/mongodb/test/db4/log/db4.log pidfilepath=/home/mongodb/test/db4/db4.pid logappend=true port=40004 fork=true configdb=mongos/172.17.237.33:30000,172.17.237.34:30001,172.17.237.36:30002 #若是有多個mongo confi的話就用逗號分隔開
[root@My-Dev bin]# ./mongos -f /home/mongodb/test/db4/mongos.conf about to fork child process, waiting until server is ready for connections. forked process: 6268 child process started successfully, parent exiting
shard2副本集集羣部署
[root@My-Dev db8]# more shard21.conf logpath=/home/mongodb/test/db8/log/db8.log pidfilepath=/home/mongodb/test/db8/db8.pid directoryperdb=true logappend=true port=60000 fork=true dbpath=/home/mongodb/test/db8/data oplogSize=512 replSet=sha shardsvr=true [root@My-Dev db9]# more shard22.conf logpath=/home/mongodb/test/db9/log/db9.log pidfilepath=/home/mongodb/test/db9/db9.pid directoryperdb=true logappend=true port=60001 fork=true dbpath=/home/mongodb/test/db9/data oplogSize=512 replSet=sha shardsvr=true [root@My-Dev db10]# more shard23.conf logpath=/home/mongodb/test/db10/log/db10.log pidfilepath=/home/mongodb/test/db10/db10.pid directoryperdb=true logappend=true port=60002 fork=true dbpath=/home/mongodb/test/db10/data oplogSize=512 replSet=sha shardsvr=true
[root@My-Dev bin]# ./mongod -f /home/mongodb/test/db8/shard21.conf [root@My-Dev bin]# ./mongod -f /home/mongodb/test/db9/shard22.conf [root@My-Dev bin]# ./mongod -f /home/mongodb/test/db10/shard23.conf
> use admin switched to db admin > sha = { _id:"sha",members:[ {_id:0,host:"sha1:60000"}, {_id:1,host:"sha2:60001"}, {_id:2,host:"sha3:60002"}]} { "_id" : "sha", "members" : [ { "_id" : 0, "host" : "sha1:60000" }, { "_id" : 1, "host" : "sha2:60001" }, { "_id" : 2, "host" : "sha3:60002" } ] } > rs.initiate(sha) { "ok" : 1 }
shard1副本集集羣部署
[root@My-Dev db5]# vim shard1.conf logpath=/home/mongodb/test/db5/log/db5.log pidfilepath=/home/mongodb/test/db5/db5.pid directoryperdb=true logappend=true port=50000 fork=true dbpath=/home/mongodb/test/db5/data oplogSize=512 replSet=shard shardsvr=true [root@My-Dev db6]# vim shard2.conf logpath=/home/mongodb/test/db6/log/db6.log pidfilepath=/home/mongodb/test/db6/db6.pid directoryperdb=true logappend=true port=50001 fork=true dbpath=/home/mongodb/test/db6/data oplogSize=512 replSet=shard shardsvr=true [root@My-Dev db7]# vim shard3.conf logpath=/home/mongodb/test/db7/log/db7.log pidfilepath=/home/mongodb/test/db7/db7.pid directoryperdb=true logappend=true port=50002 fork=true dbpath=/home/mongodb/test/db7/data oplogSize=512 replSet=shard shardsvr=true
[root@My-Dev bin]# ./mongod -f /home/mongodb/test/db7/shard1.conf [root@My-Dev bin]# ./mongod -f /home/mongodb/test/db7/shard2.conf [root@My-Dev bin]# ./mongod -f /home/mongodb/test/db7/shard3.conf
> use admin switched to db admin > shard = { _id:"shard",members:[ {_id:0,host:"shard1:50000"}, {_id:1,host:"shard2:50001"}, {_id:2,host:"shard3:50002"}] } { "_id" : "shard", "members" : [ { "_id" : 0, "host" : "shard1:50000" }, { "_id" : 1, "host" : "shard2:50001" }, { "_id" : 2, "host" : "shard3:50002" } ] } > rs.initiate(shard) { "ok" : 1 }
分片配置
分片集合中是否有數據
默認第一個添加的shard就是主shard,存放沒有被分割的shard就是主shard
在建立分片的時,必須在索引中建立的,若是這個集合中有數據,則首先本身先建立索引,而後進行分片,若是是分片集合中沒有數據的話,則就不須要建立索引,就能夠分片
登錄mongos配置分片,向分區集羣中添加shard服務器和副本集
[root@My-Dev bin]# ./mongo mongos:40004 #登錄到mongos中 mongos> sh.status() #查看分片狀態 --- Sharding Status --- sharding version: { "_id" : 1, "minCompatibleVersion" : 5, "currentVersion" : 6, "clusterId" : ObjectId("589b0cff36b0915841e2a0a2") } shards: active mongoses: "3.4.1" : 1 autosplit: Currently enabled: yes balancer: Currently enabled: yes Currently running: no Balancer lock taken at Wed Feb 08 2017 20:20:16 GMT+0800 (CST) by ConfigServer:Balancer Failed balancer rounds in last 5 attempts: 0 Migration Results for the last 24 hours: No recent migrations databases:
#首先要登錄到shard副本集中查看那個是主節點,本次實驗室使用了兩個shard副本集 sh.addShard("<replSetName>/主節點IP/port") mongos> sh.addShard("shard/shard1:50000") { "shardAdded" : "shard", "ok" : 1 } mongos> sh.addShard("sha/sha:60000") { "shardAdded" : "shard", "ok" : 1 } mongos> sh.status() #查看分片集羣已經成功把shard加入分片中 --- Sharding Status --- sharding version: { "_id" : 1, "minCompatibleVersion" : 5, "currentVersion" : 6, "clusterId" : ObjectId("589b0cff36b0915841e2a0a2") } shards: { "_id" : "sha", "host" : "sha/sha1:60000,sha2:60001,sha3:60002", "state" : 1 } { "_id" : "shard", "host" : "shard/shard1:50000,shard2:50001,shard3:50002", "state" : 1 } active mongoses: "3.4.1" : 1 autosplit: Currently enabled: yes balancer: Currently enabled: yes Currently running: no Balancer lock taken at Wed Feb 08 2017 20:20:16 GMT+0800 (CST) by ConfigServer:Balancer Failed balancer rounds in last 5 attempts: 5 Last reported error: Cannot accept sharding commands if not started with --shardsvr Time of Reported error: Thu Feb 09 2017 17:42:21 GMT+0800 (CST) Migration Results for the last 24 hours: No recent migrations databa
mongos> sh.enableSharding("zhao") #指定zhao數據庫中使用分片 { "ok" : 1 } mongos> sh.shardCollection("zhao.call",{name:1,age:1}) #在zhao數據庫和call集合中建立了name和age爲升序的片鍵 { "collectionsharded" : "zhao.call", "ok" : 1 }
sh.status()
信息mongos> sh.status() --- Sharding Status --- sharding version: { "_id" : 1, "minCompatibleVersion" : 5, "currentVersion" : 6, "clusterId" : ObjectId("589b0cff36b0915841e2a0a2") } shards: { "_id" : "sha", "host" : "sha/sha1:60000,sha2:60001,sha3:60002", "state" : 1 } { "_id" : "shard", "host" : "shard/shard1:50000,shard2:50001,shard3:50002", "state" : 1 } active mongoses: "3.4.1" : 1 autosplit: Currently enabled: yes balancer: Currently enabled: yes Currently running: no Balancer lock taken at Wed Feb 08 2017 20:20:16 GMT+0800 (CST) by ConfigServer:Balancer Failed balancer rounds in last 5 attempts: 5 Last reported error: Cannot accept sharding commands if not started with --shardsvr Time of Reported error: Thu Feb 09 2017 17:56:02 GMT+0800 (CST) Migration Results for the last 24 hours: No recent migrations databases: { "_id" : "zhao", "primary" : "shard", "partitioned" : true } zhao.call shard key: { "name" : 1, "age" : 1 } unique: false balancing: true chunks: shard 1 { "name" : { "$minKey" : 1 }, "age" : { "$minKey" : 1 } } -->> { "name" : { "$maxKey" : 1 }, "age" : { "$maxKey" : 1 } } on : shard Timestamp(1, 0)
mongos> for ( var i=1;i<10000000;i++){db.call.insert({"name":"user"+i,age:i})};
mongos> sh.status() --- Sharding Status --- sharding version: { "_id" : 1, "minCompatibleVersion" : 5, "currentVersion" : 6, "clusterId" : ObjectId("589b0cff36b0915841e2a0a2") } shards: { "_id" : "sha", "host" : "sha/sha1:60000,sha2:60001,sha3:60002", "state" : 1 } { "_id" : "shard", "host" : "shard/shard1:50000,shard2:50001,shard3:50002", "state" : 1 } active mongoses: "3.4.1" : 1 autosplit: Currently enabled: yes balancer: Currently enabled: yes Currently running: no Balancer lock taken at Wed Feb 08 2017 20:20:16 GMT+0800 (CST) by ConfigServer:Balancer Failed balancer rounds in last 5 attempts: 5 Last reported error: Cannot accept sharding commands if not started with --shardsvr Time of Reported error: Thu Feb 09 2017 17:56:02 GMT+0800 (CST) Migration Results for the last 24 hours: 4 : Success databases: { "_id" : "zhao", "primary" : "shard", "partitioned" : true } zhao.call shard key: { "name" : 1, "age" : 1 } unique: false balancing: true chunks: #數據已經分片到兩個chunks裏面了 sha 4 shard 5 { "name" : { "$minKey" : 1 }, "age" : { "$minKey" : 1 } } -->> { "name" : "user1", "age" : 1 } on : sha Timestamp(4, 1) { "name" : "user1", "age" : 1 } -->> { "name" : "user1", "age" : 21 } on : shard Timestamp(5, 1) { "name" : "user1", "age" : 21 } -->> { "name" : "user1", "age" : 164503 } on : shard Timestamp(2, 2) { "name" : "user1", "age" : 164503 } -->> { "name" : "user1", "age" : 355309 } on : shard Timestamp(2, 3) { "name" : "user1", "age" : 355309 } -->> { "name" : "user1", "age" : 523081 } on : sha Timestamp(3, 2) { "name" : "user1", "age" : 523081 } -->> { "name" : "user1", "age" : 710594 } on : sha Timestamp(3, 3) { "name" : "user1", "age" : 710594 } -->> { "name" : "user1", "age" : 875076 } on : shard Timestamp(4, 2) { "name" : "user1", "age" : 875076 } -->> { "name" : "user1", "age" : 1056645 } on : shard Timestamp(4, 3) { "name" : "user1", "age" : 1056645 } -->> { "name" : { "$maxKey" : 1 }, "age" : { "$maxKey" : 1 } } on : sha Timestamp(5, 0)
true
是均勻的false
不是均勻的mongos> sh.getBalancerState() true
選擇sharing kes'
注意點
shard
和移除shard
mongos> sh.addShard("sha4/192.168.2.10:21001")
Balancer
mongos> sh.startBalancer()
#設置時間窗口 db.settings.update({ _id : "balancer" }, { $set : { activeWindow : { start : "23:00", stop : "6:00" } } }, true )
# 查看Balancer時間窗口 mongos> db.settings.find(); { "_id" : "balancer", "activeWindow" : { "start" : "23:00", "stop" : "6:00" }, "stopped" : false } mongos> sh.getBalancerWindow() { "start" : "23:00", "stop" : "6:00" }
mongos> db.settings.update({ "_id" : "balancer" }, { $unset : { activeWindow : 1 }}); mongos> db.settings.find(); { "_id" : "chunksize", "value" : 10 } { "_id" : "balancer", "stopped" : false }
在shell腳本中執行mongodb
[root@My-Dev ~]# echo -e "use zhao \n db.call.find()" |mongo --port 60001
Mongodb片鍵的添加
mongos> use admin switched to db admin mongos> db.runCommand({"enablesharding":"zl"}) #建立zl庫中 { "ok" : 1 } mongos> db.runCommand(db.runCommand({"shardcollection":"$ent.t_srvappraise_back","key")
#!/bin/bash url=10.241.96.155 port=30000 ent=test1 ./mongo $url:$port/admin <<EOF db.runCommand({"enablesharding":"$ent"}); db.runCommand({"shardcollection":"$ent.t_srvappraise_back","key":{"sa_seid":"hashed"}}) exit; EOF
5人點贊
擁有33鑽 (約5.84元)
關注
"小禮物走一走,來簡書關注我"
讚揚
所有評論0只看做者
按時間倒序
按時間正序
1、環境說明: 一、操做系統:CentOS Linux release 7.4.1708 二、mongodb版本:...
MongoDB基礎請參考:http://blog.51cto.com/kaliarch/2044423 Mongo...
配置服務器,所有設置爲靜態地址 轉到/home目錄,建立一個mongo目錄用作實驗,咱們須要建立以下的目錄層級和空...
隨着物質生活愈來愈豐富,人們生活水平不斷提升,消費觀念也隨之改變。從過去人們只需求物質的實用性,到追求品牌消費,後...
摘要:賺個一個億的小目標不到三分鐘就完成,讓很多服裝行家羨慕妒忌恨,服裝生意盈虧參半,MCmore助你正確擁抱服裝...