
數(shù)據(jù)副本
MongoDB中的一組副本是一群mongod進(jìn)程,這些進(jìn)程維護(hù)同樣的數(shù)據(jù)集。副本集提供了冗余和高可用性,是生產(chǎn)環(huán)境部署的基礎(chǔ)。
數(shù)據(jù)冗余和可用性
通過在不同的服務(wù)器上存儲(chǔ)相同的數(shù)據(jù),副本機(jī)制保證了一定程度的容錯(cuò),即在一個(gè)數(shù)據(jù)庫掛掉后,數(shù)據(jù)服務(wù)仍然可用。
在某些情況下,副本可以提升數(shù)據(jù)的讀性能,因?yàn)橛脩艨梢詮牟煌臄?shù)據(jù)庫讀取數(shù)據(jù)。在不同的數(shù)據(jù)中心維護(hù)數(shù)據(jù)的拷貝,能夠提高分布式應(yīng)用程序的可用性。也可以維護(hù)額外的副本用于其他的目的,比如災(zāi)難恢復(fù),告警或者是備份。
Mongo中的副本
一個(gè)Mongo副本集包括幾個(gè)數(shù)據(jù)軸承節(jié)點(diǎn)和一個(gè)可選的仲裁者。在這些節(jié)點(diǎn)中,有且只有一個(gè)主節(jié)點(diǎn),其他的節(jié)點(diǎn)都被認(rèn)為是輔助節(jié)點(diǎn)。
主節(jié)點(diǎn)接收所有的寫操作。一套副本中,只有主節(jié)點(diǎn)能夠確認(rèn){ w: "majority"};雖然在一些情況下,另外的mongod進(jìn)程會(huì)在短時(shí)間內(nèi)認(rèn)為自己是主節(jié)點(diǎn)。主節(jié)點(diǎn)將所有數(shù)據(jù)的變動(dòng)記錄在日志中,比如oplog
從節(jié)點(diǎn)復(fù)制主節(jié)點(diǎn)的oplog,然后根據(jù)日志重放數(shù)據(jù)集的變動(dòng),通過這樣的方式達(dá)到和主節(jié)點(diǎn)的數(shù)據(jù)一致。如果主節(jié)點(diǎn)掛掉,一個(gè)合格的從節(jié)點(diǎn)將發(fā)起一次選舉將自己選舉為新的主節(jié)點(diǎn)。
可以在副本集中添加一個(gè)額外的mongod實(shí)例作為仲裁者。仲裁者不維護(hù)數(shù)據(jù)集,它的主要功能是維護(hù)節(jié)點(diǎn)間的心跳和響應(yīng)其他副本集成員的請(qǐng)求。因?yàn)橹俨谜卟痪S護(hù)數(shù)據(jù),因此和一個(gè)完整節(jié)點(diǎn)相比,占用的資源會(huì)更少。如果副本集中節(jié)點(diǎn)數(shù)量是偶數(shù),添加一個(gè)仲裁者可以在主節(jié)點(diǎn)的選舉中添加多數(shù)選票的能力。
仲裁者的角色不會(huì)變,主節(jié)點(diǎn)有可能會(huì)降級(jí)成從節(jié)點(diǎn),從節(jié)點(diǎn)也可能升級(jí)為主節(jié)點(diǎn)。
異步復(fù)制
從節(jié)點(diǎn)異步從主節(jié)點(diǎn)應(yīng)用操作。在從主節(jié)點(diǎn)同步數(shù)據(jù)后,即使有部分節(jié)點(diǎn)掛掉,副本集依然可以保持工作。
自動(dòng)故障轉(zhuǎn)移
當(dāng)一個(gè)主節(jié)點(diǎn)和副本集中的其他節(jié)點(diǎn)有超過10秒中的連接斷開時(shí),一個(gè)合格的從節(jié)點(diǎn)將發(fā)起選舉,將自己提升為主節(jié)點(diǎn)。第一個(gè)發(fā)起選舉并且得到副本集中大多數(shù)選票的節(jié)點(diǎn)會(huì)成為主節(jié)點(diǎn)。
故障轉(zhuǎn)移過程通常在一分鐘內(nèi)完成。副本集中的其他節(jié)點(diǎn)可能需要10到30秒來讓確認(rèn)主節(jié)點(diǎn)不可訪問。在確認(rèn)后將發(fā)起選舉。選舉的過程可能需要10到30秒。
讀操作
默認(rèn)情況下,用戶會(huì)從主節(jié)點(diǎn)中讀取數(shù)據(jù),不過用戶也可以通過設(shè)置發(fā)送讀請(qǐng)求到從節(jié)點(diǎn)。異步制意味著從節(jié)點(diǎn)中的數(shù)據(jù)可能和主節(jié)點(diǎn)并不一致。
數(shù)據(jù)分片
數(shù)據(jù)分片是將數(shù)據(jù)分散存儲(chǔ)在多個(gè)機(jī)器上。MongoDB使用分片技術(shù)來支持部署非常大的數(shù)據(jù)集,并提高系統(tǒng)的吞吐量。
單服務(wù)器會(huì)面臨大量數(shù)據(jù)和高吞吐量的應(yīng)用程序的挑戰(zhàn)。比如,高頻率的查詢會(huì)耗盡服務(wù)器的CPU資源;大于系統(tǒng)內(nèi)存的工作數(shù)據(jù)集會(huì)對(duì)磁盤的I/O造成很大壓力。
有兩種方式來應(yīng)對(duì)系統(tǒng)數(shù)據(jù)的增長(zhǎng):垂直擴(kuò)展和水平擴(kuò)展。
垂直擴(kuò)展包括增加單個(gè)服務(wù)器的能力,比如使用更強(qiáng)的CPU,添加更多內(nèi)存,或者增加存儲(chǔ)空間?,F(xiàn)有技術(shù)的局限可能讓單臺(tái)機(jī)器無法應(yīng)對(duì)某個(gè)給定的工作負(fù)載。另外,云服務(wù)商能夠提供的硬件配置也有一定的上限。因此在實(shí)踐中,垂直擴(kuò)展能夠應(yīng)對(duì)的負(fù)載有上限。
水平擴(kuò)展包括數(shù)據(jù)集的劃分,和多臺(tái)服務(wù)器分?jǐn)傌?fù)載,水平擴(kuò)展可以通過添加新的機(jī)器來提升處理能力。雖然單機(jī)的能力可能不是很強(qiáng),但是每臺(tái)機(jī)器都負(fù)責(zé)處理整體負(fù)載的一個(gè)子集,因此有能力提供比高速大容量服務(wù)器更高的效率。水平擴(kuò)展提升系統(tǒng)的處理能力只需要添加新的服務(wù)器,這比提升高端服務(wù)器性能所需的成本要低。缺點(diǎn)是增加了基礎(chǔ)設(shè)施部署和維護(hù)的復(fù)雜度。
MongoDB通過分片技術(shù)支持系統(tǒng)的水平擴(kuò)展。
分片集群
MongoDB的分片集群中有以下組件:
- shard:每個(gè)shard都包含數(shù)據(jù)分片的一個(gè)子集。每個(gè)shard都可以部署為一個(gè)副本集
- mongos:mongos作為查詢路由,提供客戶端應(yīng)用程序和分片集群之間的接口
- config servers:config servers存儲(chǔ)集群中的元數(shù)據(jù)和配置數(shù)據(jù)。在Mongo3.4中,config server必須被部署為副本集。
下圖展示了各個(gè)組件之間的交互。
Shard Keys
MongoDB使用shard key對(duì)collection的數(shù)據(jù)分片。shard key由一個(gè)不可變的字段或目標(biāo)collection中每個(gè)文檔都存在的字段組成。
需要在對(duì)collection分片的時(shí)候選擇shard key。shard key之后不能更改。一個(gè)分片的collection只能有一個(gè)shard key。
要對(duì)一個(gè)非空collection分片,collection必須有一個(gè)由shard key開始的索引。對(duì)于空的collection,如果沒有一個(gè)合適索引,MongoDB會(huì)創(chuàng)建索引。
shard key的選擇會(huì)影響集群的性能,效率和可擴(kuò)展性。shard key可能會(huì)成為集群的瓶頸,即使集群中的機(jī)器性能都很高。
chunks
MongoDB將數(shù)據(jù)分片到chunk中。依據(jù)選擇的shard key,每個(gè)chunk大小都有下限和上限。
在集群中,MongoDB使用分片集群均衡器遷移各個(gè)chunk。均衡器試圖實(shí)現(xiàn)在集群中chunk的均衡。
分片的優(yōu)點(diǎn)
讀/寫
MongoDB在分片集群中,將讀和寫的負(fù)載分配到各個(gè)節(jié)點(diǎn)中,允許每個(gè)shard處理集群操作的一個(gè)子集??梢酝ㄟ^添加更多的shard橫向擴(kuò)展這種讀寫能力。
對(duì)于包括shard key的查詢,mongos可以將查詢定位到特定的shard。
存儲(chǔ)性能
分片技術(shù)將數(shù)據(jù)分配到集群中的節(jié)點(diǎn)上,每個(gè)shard包含總數(shù)據(jù)集合的一個(gè)子集。隨著數(shù)據(jù)集的增長(zhǎng),添加shard能夠增加集群的存儲(chǔ)容量。
高可用
即使在部分shard不可用的情況下,集群依然可以繼續(xù)執(zhí)行部分讀/寫操作。在掛掉的shard不可用期間,可用的shard的讀寫不受影響。
在生產(chǎn)環(huán)境中,shard應(yīng)該部署為副本集,以提供數(shù)據(jù)冗余和可用性。
分片注意事項(xiàng)
在集群上實(shí)施分片需要仔細(xì)地規(guī)劃,執(zhí)行和維護(hù)。
仔細(xì)選擇shard key,對(duì)于確保集群的性能和效率是必要的。在分片后不能改變shard key,也不能撤銷分片。
分片有一定的操作要求和限制。
如果查詢不包括shard key,mongos會(huì)廣播操作,在集群中的shard中執(zhí)行查詢。這樣的查詢可能有較長(zhǎng)耗時(shí)。
分片和非分片collection
一個(gè)數(shù)據(jù)庫可能同時(shí)有分片的collection和非分片的collection。分片的collection是分區(qū)的,分布在集群的不同shard中。非分片的collection存儲(chǔ)在主shard中。每個(gè)數(shù)據(jù)庫都有自己的主shard。
分片集群的連接
必須連接到mongos路由,來與分片集群中的collection交互。這種交互包括分片collection和非分片collection??蛻舳瞬辉试S直接連接到單獨(dú)的shard來進(jìn)行讀寫操作。
分片策略
MongoDB支持兩種分片策略。
哈希分片
哈希分片是對(duì)shard key的值進(jìn)行哈希運(yùn)算后進(jìn)行分片。每個(gè)chunk基于哈希后的值進(jìn)行分配。
一個(gè)范圍內(nèi)的shard key可能很接近,但是hash后的結(jié)果很可能不在同一個(gè)chunk中?;诠5臄?shù)據(jù)分布會(huì)形成更加均衡的數(shù)據(jù)分布,特別是在shard key單調(diào)變化的情況下。
但是,哈希分布意味著對(duì)范圍查詢不太可能定位到單個(gè)shard,這會(huì)導(dǎo)致廣播操作。
范圍分片
范圍分片是將數(shù)據(jù)基于shard key的值進(jìn)行切分。每個(gè)chunk基于shard key的值進(jìn)行分配。
shard key某個(gè)范圍內(nèi)的值更可能分配在相同的chunk中,mongos會(huì)將請(qǐng)求導(dǎo)向只含有請(qǐng)求數(shù)據(jù)的shard中。
范圍分片的效率取決于shard key。欠考慮的shard key會(huì)導(dǎo)致數(shù)據(jù)的分布不均,這會(huì)減少數(shù)據(jù)分片的優(yōu)勢(shì)或者導(dǎo)致性能瓶頸。
分片集群的區(qū)域
在分片集群中,可以基于shard key創(chuàng)建數(shù)據(jù)區(qū)域??梢园鸭褐械亩鄠€(gè)shard在同個(gè)區(qū)域中關(guān)聯(lián)起來。一個(gè)shard可以和任意數(shù)量的非沖突區(qū)域關(guān)聯(lián)起來。在平衡的集群中,MongoDB會(huì)將區(qū)域中的chunk遷移到區(qū)域里關(guān)聯(lián)的shard中。
每個(gè)區(qū)域包括一個(gè)或多個(gè)范圍的shard key。每個(gè)區(qū)域的覆蓋范圍總是包容它的下邊界和排它的上界。