MongoDB的分片集群
分片集群簡介
在之前有說過關(guān)于MongoDB的復(fù)制集,復(fù)制集主要用來實現(xiàn)自動故障轉(zhuǎn)移從而達(dá)到高可用的目的,然而,隨著業(yè)務(wù)規(guī)模的增長和時間的推移,業(yè)務(wù)數(shù)據(jù)量會越來越大,當(dāng)前業(yè)務(wù)數(shù)據(jù)可能只有幾百GB不到,一臺DB服務(wù)器足以搞定所有的工作,而一旦業(yè)務(wù)數(shù)據(jù)量擴(kuò)充大幾個TB幾百個TB時,就會產(chǎn)生一臺服務(wù)器無法存儲的情況,此時,需要將數(shù)據(jù)按照一定的規(guī)則分配到不同的服務(wù)器進(jìn)行存儲、查詢等,即為分片集群。分片集群要做到的事情就是數(shù)據(jù)分布式存儲。
分片部署架構(gòu)
架構(gòu)設(shè)計
先看一張圖:
先做一些解釋:
1.shard片:一般為一臺單獨的服務(wù)器,即為一個數(shù)據(jù)存儲節(jié)點,這個存儲節(jié)點需要做復(fù)制集,實現(xiàn)高可用以及自動故障轉(zhuǎn)移,一般一個分片集群有多個shard片;
2. config服務(wù)器:主要是記錄shard的配置信息(元信息metadata),如數(shù)據(jù)存儲目錄,日志目錄,端口號,是否開啟了journal等信息,為了保證config服務(wù)器的可用性,也做了復(fù)制集處理,注意,一旦配置服務(wù)器無法使用,則整個集群就不能使用了,一般是獨立的三臺服務(wù)器實現(xiàn)冗余備份,這三臺可能每一臺是獨立的復(fù)制集架構(gòu)。
3.Mongos路由進(jìn)程(Router):應(yīng)用程序通過驅(qū)動程序直接連接router,router啟動時從配置服務(wù)器復(fù)制集中讀取shared信息,然后將數(shù)據(jù)實際寫入或讀取(路由)到具體的shard中。
部署配置
注意:此處由于我這邊只有一臺服務(wù)器(PC機(jī)),所以這里實現(xiàn)的是一個偽集群,部署架構(gòu)如圖所示:
一個Shard(復(fù)制集模式),一個config進(jìn)程,一個router進(jìn)程,均在同一臺服務(wù)器上面
沿用上一節(jié)的復(fù)制集作為shard,
啟動:
mongod --dbpath=D:\MongoDB\Server\3.2\data\rs0_0 --logpath=D:\MongoDB\Server\3.2\logs\rs0_0.log --port=40000 --replSet=rs0 mongod --dbpath=D:\MongoDB\Server\3.2\data\rs0_1 --logpath=D:\MongoDB\Server\3.2\logs\rs0_1.log --port=40001 --replSet=rs0 mongod --dbpath=D:\MongoDB\Server\3.2\data\rs0_2 --logpath=D:\MongoDB\Server\3.2\logs\rs0_2.log --port=40002 --replSet=rs0配置服務(wù)器啟動:
mongod --dbpath=D:\MongoDB\Server\3.2\data\db_config --logpath=D:\MongoDB\Server\3.2\logs\dbconfig.log --port=40003 --configsvr路由服務(wù)器啟動
mongos --logpath=D:\MongoDB\Server\3.2\logs\dbrouter.log --port=40004 --configdb=linfl-PC:40003添加分片信息到集群:
mongo --port 40004 mongos> use admin switched to db admin mongos> sh.addShard("rs0/linfl-PC:40000,linfl-PC:40001") {"ok" : 0,"errmsg" : "can't add shard 'rs0/linfl-PC:40000,linfl-PC:40001' because a local database 'config' exists in another config","code" : 96 }報錯了,原來的rs0由于已經(jīng)存在config數(shù)據(jù)庫了,去把他刪掉:
D:\MongoDB\Server\3.2\bin>mongo --port 40000 2017-02-27T16:14:51.454+0800 I CONTROL [main] Hotfix KB2731284 or later update is not installed, will zero-out data files MongoDB shell version: 3.2.9 connecting to: 127.0.0.1:40000/test rs0:PRIMARY> show dbs cms 0.000GB config 0.000GB local 0.000GB test 0.000GB rs0:PRIMARY> use config switched to db config rs0:PRIMARY> db.dropDatabase() { "dropped" : "config", "ok" : 1 }然后重新連接到4004執(zhí)行添加分片即可,看下狀態(tài):
D:\MongoDB\Server\3.2\bin>mongo --port 40004 2017-02-27T16:15:17.286+0800 I CONTROL [main] Hotfix KB2731284 or later update is not installed, will zero-out data files MongoDB shell version: 3.2.9 connecting to: 127.0.0.1:40004/test mongos> sh.addShard("rs0/linfl-PC:40000,linfl-PC:40001") { "shardAdded" : "rs0", "ok" : 1 } mongos> sh.status() --- Sharding Status ---sharding version: {"_id" : 1,"minCompatibleVersion" : 5,"currentVersion" : 6,"clusterId" : ObjectId("58b3d9df84493cb599359c8b") }shards:{ "_id" : "rs0", "host" : "rs0/linfl-PC:40000,linfl-PC:40001" }active mongoses:"3.2.9" : 1balancer:Currently enabled: yesCurrently running: noFailed balancer rounds in last 5 attempts: 5Last reported error: remote client 192.168.56.1:51845 tried to initiali ze this host as shard rs0, but shard name was previously initialized as configTime of Reported error: Mon Feb 27 2017 16:15:48 GMT+0800Migration Results for the last 24 hours:No recent migrationsdatabases:{ "_id" : "cms", "primary" : "rs0", "partitioned" : false }{ "_id" : "test", "primary" : "rs0", "partitioned" : false }對config數(shù)據(jù)庫中的各個集合做如下解釋:
mongos> use config switched to db config mongos> show collections actionlog // changelog //保存被分片的集合的任何元數(shù)據(jù)的改變信息,如chunks的遷移,分割等 chunks //集群中所有的塊信息,塊的數(shù)據(jù)范圍以及塊所在的片 databases //集群中所有的數(shù)據(jù)庫 lockpings //追蹤集群中的激活組件 locks//均衡器產(chǎn)生的鎖信息 mongos//所有路由信息 settings//分片集群的配置信息,如chunk大小,均衡器狀態(tài)等 shards//集群中所有的片信息 tags version//元信息版本注意:對集群的操作應(yīng)該都是通過客戶端連接mongos路由來執(zhí)行。
正常來講,一個完整的生產(chǎn)環(huán)境至少需要9個Mongod實例,一個Mongos實例,10臺機(jī)器才能組成,而由于可以對部分實例采用合并在一臺機(jī)器上進(jìn)行部署的操作(對資源消耗較低,或?qū)Y源消耗的類型不同),能夠得到典型的部署結(jié)構(gòu)如下:
以上部署方案使得每個shard(復(fù)制集)中的節(jié)點完全分開到不同的服務(wù)器上,并將config服務(wù)分開,使得其中任何一臺服務(wù)器宕機(jī),集群都可正常工作,當(dāng)然我認(rèn)為,最少只需要三臺服務(wù)器即可構(gòu)成穩(wěn)定的集群(3壞1可正常工作),然而卻非典型的架構(gòu)了。
分片工作機(jī)制
MongoDB的分片是基于集合(表)來進(jìn)行的,要對一個集合分片,就要像使其所在的數(shù)據(jù)庫支持分片。
集合分片
MongoDB的分片是基于返回的,即任何一個文檔一定位于指定片鍵的某個范圍內(nèi),一單片鍵選擇好以后,chunks就會按照片鍵將一部分documents從邏輯上組合在一起
如:對users集合選擇city作為片鍵來分片,如果city字段中存在 ‘beijing’,’guangzhou’,’changsha’,初始時隨機(jī)的向集群中插入文檔,由于初始時chunks比較小,沒有達(dá)到閾值64MB或10000個文檔,不需要分片,隨著繼續(xù)插入,超過chunk閾值后chunk被分割成兩個,最終分步可能如下所示:
開始鍵值 – 結(jié)束鍵值 –所在分片
開始鍵值 結(jié)束鍵值 所在分片
| -∞ | beijing | rs0 |
| beijing | changsha | rs1 |
| changsha | guangzhou | rs0 |
| guangzhou | ∞ | rs1 |
需要注意的是:chunks所包含的文檔并非物理上包含,而是一種邏輯包含,指標(biāo)是帶有片鍵的文檔會落在那個范圍內(nèi)。
使集合支持分片,必須先使數(shù)據(jù)庫支持分片:
sh.enableSharding('cms')對于已有的集合如果要分片,那么選定片鍵后,需要在片鍵上面首先創(chuàng)建索引,如果集合初始狀態(tài)為空,則自動創(chuàng)建索引
查看rs.status()可以看到,如下信息片段:
證明 cms已經(jīng)支持分片
在已存在的集合中分片
先創(chuàng)建索引:
注意:由于我本地是單臺PC,做分片后看不到效果,但如果有兩個分片,分別為rs0,與rs1,往users中插入數(shù)據(jù),最后的結(jié)果會是
通過
db.changelog.find()可以看到具體的塊分割過程,當(dāng)存儲的chunk小于64MB時,不分割,當(dāng)大于64MB時,開始分割成兩部分,-∞~beijing,beijing~∞,隨著數(shù)據(jù)的進(jìn)一步增大,beijing~∞被繼續(xù)分割成beijing~guangzhou,guangzhou~∞,這樣,rs0就有三個chunk了,隨后,-∞到beijing的chunk開始發(fā)生轉(zhuǎn)移,從rs0遷移到rs1上面去,依次類推,MongDB就是這樣實現(xiàn)了海量數(shù)據(jù)的分布式存儲的。
集群平衡器
在上一步的操作中最后講到了塊chunk從rs0遷移到rs1的操作,這個動作是由 平衡器的后臺進(jìn)程自動完成的。
當(dāng)一個被分片的集合的所有chunk在集群中分布不均衡時(如200個chunk在rs0,50個在rs1上),平衡器就會將chunk從最多的片上遷移到最少的片上,直到chunk數(shù)量基本相等為止。平衡器會根據(jù)chunk數(shù)量的不同,有不同的規(guī)則觸發(fā)塊遷移,默認(rèn)配置為chunk<20,閾值為2,20 < chunk<79閾值為4,chunk>80,閾值為8,這也就是為什么我們在剛才要在chunk為3時才能看到遷移過程的變化。
基本的chunk遷移流程如下所示:
本示例中源片指的是rs0,目標(biāo)片指的是rs1
集群的寫、讀
集群的讀、寫與單個MongoDB的讀寫是一樣的,對應(yīng)用程序時透明的,這里主要看分片集群對性能的影響。
片鍵是決定查詢落到哪一個chunk上的依據(jù),這個信息保存在配置服務(wù)器上,而索引是針對每個片上的集合來說的,每個片都會為自己的集合創(chuàng)建索引數(shù)據(jù),因此,查詢語句中是否包含片鍵與索引對查詢性能影響較大。
可以通過explain解釋執(zhí)行查看,需要注意幾個點:
nscanned:查詢用到索引時,索引中掃描的文檔數(shù)
nscannedObjects:在集合中掃描的文檔數(shù)
nscannedAllPlans:所有查詢計劃中掃描的文檔總數(shù)
nscanned:選定的某一種查詢計劃下掃描的文檔總數(shù)
片鍵選擇策略
好的片鍵應(yīng)該具有如下特質(zhì):
通常我們需要由幾個字段組合作為片鍵,如city+_id,既能夠保證同一city下的文檔盡量分布在同一個片上,_id則保證了chunk能夠一直被分割。
在實際業(yè)務(wù)中可以考慮order表中 company_id與create_date或id共同組成片鍵。
注意
只有當(dāng)數(shù)據(jù)量很大、讀寫請求很高時才適合用分片集群。
參考鏈接
https://docs.mongodb.com/manual/core/sharded-cluster-components
總結(jié)
以上是生活随笔為你收集整理的MongoDB的分片集群的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一步一步实战HTML音乐播放器
- 下一篇: WonderTrader高频交易初探及v