mongos
查詢與寫入操作利用MongoDB的mongos實(shí)例在集群中進(jìn)行路由。從應(yīng)用程序的角度來看,mongos提供了訪問集群的唯一接口踪宠。應(yīng)用程序從不直接跟碎片連接或交互代咸。
mongos從config servers緩存元數(shù)據(jù)從而追蹤哪個(gè)數(shù)據(jù)在哪個(gè)碎片上译荞。mongos利用元數(shù)據(jù)將應(yīng)用程序和客戶端的操作路由到mongod實(shí)例上瞪醋。mongos沒有持續(xù)的狀態(tài)并且不怎么消耗系統(tǒng)資源。
練習(xí)過程中推薦將mongos實(shí)例跟你的應(yīng)用程序服務(wù)器部署在同一個(gè)系統(tǒng)上装诡,但你也可以在碎片或其他專用資源上維護(hù)mongos實(shí)例银受。
Routing And Results Process
mongos實(shí)例通過以下兩點(diǎn)在集群里路由查詢操作:
- 確定必須回應(yīng)查詢的碎片條目。
- 在所有目標(biāo)碎片上建立游標(biāo)鸦采。
然后mongos會把每一個(gè)目標(biāo)碎片的數(shù)據(jù)合并宾巍,且返回結(jié)果文檔。某些查詢修飾符(如sorting),會在mongos檢索結(jié)果之前的上一個(gè)碎片上進(jìn)行以上操作(跟primary shard一樣)渔伯。
MongoDB3.6以后對于在多碎片上進(jìn)行的聚合操作顶霞,如果不用在數(shù)據(jù)庫的primary shard進(jìn)行操作,這些操作會被返回到monogs進(jìn)行合并锣吼。
以下兩種管道無法運(yùn)行 mongos
:
第一種情況是管道的拆分合并部分包含必須運(yùn)行在主碎片上運(yùn)行的階段時(shí)选浑。例如,$lookup操作在一個(gè)未碎片化的集合上發(fā)出請求玄叠,而該集合和一個(gè)正在聚合的碎片化集合在同一個(gè)數(shù)據(jù)庫古徒,那么該階段就應(yīng)該運(yùn)行在primary shard上。
第二種情況是管道的拆分合并部分包含有可能將臨時(shí)數(shù)據(jù)寫入磁盤時(shí)读恃,例如$group操作符,并且客戶端指定了allowDiskUse:true隧膘,這種情況下,即使假設(shè)沒有其他需要在primary shard運(yùn)行的管道合并階段寺惫,但合并操作會在聚合操作的目標(biāo)碎片上隨機(jī)找一個(gè)進(jìn)行疹吃。
要獲得更多集群聚合查詢是如何分割組件的信息,將explain:true作為參數(shù)傳遞給 aggregation() 方法西雀。結(jié)果會包含三個(gè)json對象萨驶。
- mergeType字段表示合并操作在哪個(gè)階段進(jìn)行(“primaryShard”, “anyShard”, or “mongos”).
- splitPipeline字段表示管道內(nèi)的哪個(gè)操作必須運(yùn)行在私有碎片上。
- shards字段表示每個(gè)碎片已經(jīng)完成的工作艇肴。
在某些情況下篡撵,當(dāng)shard key或者shard key的前綴是查詢的一部分,mongs會執(zhí)行 targeted operation豆挽,將查詢路由到集群的碎片的子集上育谬。
mongos將不包含shard key的查詢操作以廣播形式發(fā)送,路由到集群里的所有碎片上帮哈。取決集群內(nèi)數(shù)據(jù)的分布和查詢的選擇膛檀,一些不包含shard key的查詢或許依然會對廣播進(jìn)行回應(yīng)。
mongos如何處理查詢操作符
Sorting
如果查詢的結(jié)果沒有排序,mongos實(shí)例返回從所有的碎片游標(biāo)上打開"一系列"的結(jié)果游標(biāo)咖刃。
如果使用了游標(biāo)方法 sort()
對查詢結(jié)果進(jìn)行了排序泳炉,mongos實(shí)例將 $orderby
選項(xiàng)傳遞給碎片。數(shù)據(jù)庫的primary shard在通過mongos將數(shù)據(jù)返回給客戶端之前會對結(jié)果進(jìn)行接受和執(zhí)行合并排序嚎杨。
Limits
如果使用了游標(biāo)方法 limit()
對結(jié)果的大小進(jìn)行了limits花鹅。那mongos實(shí)例在將數(shù)據(jù)返回給客戶端前該limit操作傳送給碎片然后再將該limit操作重新應(yīng)用在結(jié)果上。
Skips
如果使用了游標(biāo)方法 skip()
跳過了一系列記錄枫浙,mongos不會將skip操作傳遞給碎片刨肃,而是檢索碎片內(nèi)沒有被跳過的記錄且當(dāng)收集結(jié)果的時(shí)候跳過文檔內(nèi)適當(dāng)?shù)臈l目。
當(dāng)使用 與 limit()
方法同時(shí)使用時(shí)箩帚,mongos會將limit()
加上skip()
的結(jié)果傳遞給碎片以此來提升這些操作的效率真友。
確保mongos實(shí)例連接成功
要確保你的MongoDB實(shí)例已經(jīng)連接上mongos,使用isMaster
命令紧帕。當(dāng)客戶端連接到 mongos
盔然,isMaster
會返回一個(gè)帶有isdbgrid字符串的msg字段。例如:
{
"ismaster" : true,
"msg" : "isdbgrid",
"maxBsonObjectSize" : 16777216,
"ok" : 1,
...
}
相反如果你的應(yīng)用是連接到mongod是嗜,那么返回的文檔不會有isdbgrid字符串愈案。
Query Isolation
通常,在碎片化環(huán)境下鹅搪。通過shard key和來自config server的集群元數(shù)據(jù)刻帚,mongos將查詢路由到單碎片的查詢效率是最高的。 targeted operations使用shard key的值來定位復(fù)合查詢條件的碎片或者碎片的子集涩嚣。
對于那些不包含shard key的查詢崇众,mongos必須對所有碎片進(jìn)行查詢,然后等待碎片的回應(yīng)再把結(jié)果返回給應(yīng)用程序航厚。這種"收/發(fā)"查詢或許需要更長時(shí)間才能運(yùn)行完畢顷歌。
Broadcast Operations
除非mongos可以直接確定哪個(gè)碎片或者碎片的子集持有查詢的數(shù)據(jù),否則mongos實(shí)例將直接將查詢操作廣播到所有碎片上幔睬。
[圖片上傳失敗...(image-e37c94-1520269344158)]
當(dāng)mongos收到所有碎片的回應(yīng)后眯漩,會將數(shù)據(jù)合并并且返回結(jié)果文檔。集群內(nèi)的負(fù)載決定了廣播的效率麻顶,例如網(wǎng)絡(luò)延遲赦抖,單個(gè)碎片的負(fù)載,和每個(gè)碎片要返回的文檔數(shù)量辅肾,都能影響廣播的性能队萤。
更新多個(gè)文檔的指令都只進(jìn)行廣播。
updateMany()
和 deleteMany()
都只能進(jìn)行廣播操作矫钓,除非查詢條件全額指定為shard key要尔。
Targeted Operations
mongos可以將帶有shard key或者shard key作為聚合前綴的查詢路由到碎片或者碎片集上舍杜。mongs利用shard key值來定位到包含shard key的范圍的chunk上并且直接將該查詢執(zhí)行在該chunk的碎片中。
[圖片上傳失敗...(image-38535d-1520269344158)]
例如赵辕,如果shard key是:
{ a: 1, b: 1, c: 1 }
mongos可以將包含全部shard key值或者shard key前綴的查詢路由到指定碎片或者包含數(shù)據(jù)的多個(gè)碎片上:
{ a: 1 }
{ a: 1, b: 1 }
任何 insertOne()
操作都只命中一個(gè)碎片既绩。insertMany()
里的每個(gè)文檔都只命中單個(gè)碎片,但不保證所有文檔都被插入到同一個(gè)碎片上还惠。
所有 updateOne()
, replaceOne()
and deleteOne()
操作都必須包含shard key或者_id作為查詢條件饲握。否則MongoDB會直接報(bào)錯(cuò)。
根據(jù)集群里數(shù)據(jù)的分布和查詢的選擇蚕键,mongos可能依然會對查詢進(jìn)行廣播救欧。
Index Use
如果查詢條件文檔不包含shard key,mongos必然會將該查詢以廣播形式發(fā)送到集群里的所有碎片上嚎幸。反過來,使用shard key索引或者其他更高效的索引來進(jìn)行查詢寄猩。
如果查詢包含多個(gè)引用了shard key和輔助索引字段的子表達(dá)式嫉晶,mongos會把該查詢路由到指定的碎片上并且該索引會令碎片更高效的完成工作。
Sharded Cluster Security
使用 Internal Authentication來確保集群的內(nèi)部安全和避免未授權(quán)用戶訪問集群田篇。為確保集群內(nèi)部安全替废,你必須為每一個(gè)mongos和mongod實(shí)例配置適當(dāng)?shù)陌踩栽O(shè)置。
集群用戶
分片集群支持使用 Role-Based Access Control (RBAC)來限制未授權(quán)用戶訪問和操作集群內(nèi)的數(shù)據(jù)泊柬。要開啟(RBAC)椎镣,你必須在啟動mongod實(shí)例時(shí)指定--auth選項(xiàng)(包括config servers在內(nèi))。另外兽赁,為集群內(nèi)部開啟了 Internal Authentication状答,MongoDB會自動為你打開RBAC。
如果指定了RBAC刀崖,客戶端在連接mongos來操作集群的時(shí)候惊科,要指定--username,--password和--authenticationDatabase選項(xiàng)。
每個(gè)集群的用戶是相互獨(dú)立的亮钦,并且這些用戶都不能訪問集群內(nèi)的單個(gè)碎片馆截。