MongoDB 3.4 分片 由副本集組成


要在真實環境中實現MongoDB分片至少需要四台服務器做分片集群服務器,其中包含兩個Shard分片副本集(每個包含兩個副本節點及一個仲裁節點)、一個配置副本集(三個副本節點,配置不需要仲裁節點),其中Shard的副本節點必須擁有單獨的服務器,通常一個Shard副本集由3個以上副本節點組成更好,奇數個副本節點不需要額外配置仲裁節點。因為仲裁節點和配置節點不需要耗費很多的資源,可以與其他進程共享一台服務器。

當然了,對於平時學習而言,配置那么多服務器是不現實的,用VM虛擬機也不現實,畢竟MongoDB內存開銷不小,所以暫時將所有需要的數據庫配置在同一台電腦,以不同端口區分,其中包含以下幾個數據庫

Shard節點

  Shard-a-1 端口 37001

  Shard-a-2 端口 37002

  Shard-a-3 端口 37003

--------------------------------------------------------------------  

   Shard-b-1 端口 37011

   Shard-b-2 端口 37012

   Shard-b-3 端口 37013

 

Config節點

  Config-1 端口 41001

  Config-2 端口 41002

  Config-3 端口 41003

 

Router節點

  Router 端口 50000

文件目錄大概如下,其中router中的config改為 mongos.cfg

其中Shard節點和Config節點和開啟普通MongoDB數據庫一樣,用Mongod啟動,在Windows下不能使用 fork參數后台化,個人更推薦使用Service來托管

其中Shard節點的配置如下,每個文件夾下對應的配置把dbpath/logpath/replSet(shard-a和shard-b)改掉,因為要開啟多個db所以httpinterface設置為false,不開啟監聽,否則每個db都會對應多一個端口號+1000的監聽端口,37002的監聽端口為38002 

dbpath=D:\mongodatas\shard-a2\data
logpath=D:\mongodatas\shard-a2\log\mongod.log
logappend=true
directoryperdb=true
rest=true
httpinterface=false
port=37002
shardsvr=true
replSet=shard-a

Config節點的配置如下,與shard節點的區別就是shardsvr換成了configsvr,配置服務器是不會開啟監聽端口的

dbpath=D:\mongodatas\config1\data
logpath=D:\mongodatas\config1\log\mongod.log
logappend=true
directoryperdb=true
rest=true
port=41001
configsvr=true
replSet=configset

接下來以托管到Service的方式啟動所有的Shard節點和Config節點,以下只是啟動其中一個,一共有九個(shard-a有3個,shard-b有3個,config有3個),在命令提示符(管理員) 的窗口執行,普通權限會報錯的,下文用到Service的一樣

sc create MongoShardA1 binPath= "C:\Program Files\MongoDB\Server\3.4\bin\mongod.exe --config=D:\mongodatas\shard-a1\mongod.cfg --service"
net start MongoShardA1

使用命令  services.msc打開服務窗口查看服務是否開啟或者使用 netstat -nao指令查端口是否開啟,如果全都正常開啟,則開始配置Shard副本集

任意連接shard-a中服務器 (37001/37002/37003)打開MongoDB Shell

mongo --port 37001

對副本集進行初始化,如果對rs方法不熟悉,可以使用rs.help()顯示幫助文檔

rs.initiate()

此時發現37001端口的命令輸入已經成為了副本集的形式,接下來添加另外兩個成員,一個副本節點,一個仲裁節點

rs.add("localhost:37002")
rs.add("localhost:37003",{arbiterOnly:true})

最好使用本機的內網地址,而不是使用localhost或者127.0.0.1

 接下來查看副本集是否運行正常

rs.status()

退出現有MongoDB Shell或者開啟新的CMD進入Shard-b中任意服務器對Shard-b副本集進行初始化,進入Config副本集任意服務器對Config副本集進行初始化,注意Config副本集進行初始化的時候不需要指定仲裁節點

以上所有操作,對Config副本集進行初始化非常重要,網上有很多示例都沒有對Config副本集進行初始化,會導致mongos服務無法開啟,連接不上router服務器

現在開始配置router的配置mongos.cfg

configdb=configset/DESKTOP-4NVUAKK:41001,192.168.20.229:41002,192.168.20.229:41003
logpath=D:\mongodatas\router\log\mongod.log
logappend=true
port=50000

注意configdb的配置,新版本里面采用 replSet/hsot:port,host:port的形式,其中host必須采用config副本集里面rs.status()出來的members中的name,否則會執行失敗,如果configdb中的副本集沒有執行初始化設定Primary ,此時用Service是無法啟動成功的,但是用指令啟動會給人一種啟動成功的假象,查看router對應的日志會發現一只在嘗試連接Config副本集: No primary detected for set configset,此時查看任務管理器會發現有mongos的進程,查看端口會發現router的端口並未打開 

 

以托管到Service的方式開始Router服務

sc create MongoRouter binPath= "C:\Program Files\MongoDB\Server\3.4\bin\mongos.exe --config=D:\mongodatas\shard-a1\mongos.cfg --service"
net start MongoRouter

注意上面的執行程序是mongos而不是mongod 配置文件名不要弄錯了

正常啟動Router服務器之后,連接到router數據庫的MongoDB Shell

mongo --port 50000

開始為router指定分片副本集,具體操作如截圖所示

sh.addShard("replSet/host:port,host:port")

注意不要使用localhost或者127.0.0.1,否則會報錯

使用與副本集Members里面name不一致的host也是會報錯的

正常情況下添加成功如下

查看數據庫config中的shards集合

db.getSiblingDB("config").shards.find() 或者 db.runCommand({listshards:1})

 到現在為止,分片環境已經搭建成功,但要引用到數據庫和文檔上,還需要對數據庫和文檔進行分片

 

 

 開啟一個數據庫上的分片,這是對任何集合進行分片的先決條件

sh.enableSharding("dbName") 

完成之后去config里查看是否分片

db.getSiblingDB("config").databases.find()

 

對數據庫上的某個集合進行分片,要定義一個分片鍵,可以使用組合分片建,像我使用的是author和_id的組合,如果是對現有集合進行分片,必須在運行shardcollection命令前創建一個與分片鍵對應的索引

sh.shardCollection("dbName.collectionName",{key1:1,key2:1})

db.getSiblingDB("config").collections.find()

 

對空集合進行、分片時 MongoDB會字每個分片上創建一個與分片鍵對應的索引,可以直接連接分片,用getIndexes()驗證,此時數據量還沒達到分片標准啊,分片shard-a副本集還沒有創建books

 

用客戶端連接router服務器(和連接普通服務器一樣)插入大量數據,調用sh.status()可以看到分配到兩個shard上保存了

db.chunks.count("shard","shard-a")

db.chunks.count("shard","shard-b")

 

查看拆分次數

db.changelog.count({what:"split"}) 

查看遷移次數

db.changelog.find({what:"moveChunk.commit"}).count()

 

可以通過db.books.find(****).explain() 查看執行計划

如果查詢條件包含分片鍵,則能很快找到對應分區 針對性查詢,否則將遍歷所有分區 全局/分散/聚集查詢

 

db.books.ensureIndex({title:1}) 在title上創建索引

 

每個分片都維護自己的索引,每個分片上的分片集合都應該擁有相同的索引

分片集合只允許在_id字段和分片鍵上添加唯一索引

分片鍵是不可以修改的,不要使用升序分片鍵,粒度不能太細(如照片就不應該按md5分,而應該按所屬人分)

 

副本集的每個成員都應該在一個單獨的服務器上,用於復制的成員要有自己的機器,

仲裁節點和配置節點可以與其他進程共享主機,但需要部署在不同服務器

少數大分片比大量小分片好

 

手動塊拆分

sh.splitAt("dbname.collectionName",{key,value,key:value}) 根據key分塊  value是數據庫中的值,根據這個值拆分成兩塊

sh.moveChunk("dbname.collectionName",{key,value},"shardB") 將包含key為value的文檔移動到分片B

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM