自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

精通 MongoDB 7 :復(fù)制和分片,來(lái)審視 MongoDB 的架構(gòu)

數(shù)據(jù)庫(kù) MongoDB
MongoDB中的復(fù)制是一個(gè)通過(guò)在多個(gè)服務(wù)器間同步數(shù)據(jù)來(lái)提供冗余和提高數(shù)據(jù)可用性的過(guò)程。這是通過(guò)副本集實(shí)現(xiàn)的,副本集是一組維護(hù)相同數(shù)據(jù)集的MongoDB服務(wù)器。

MongoDB 通過(guò)建立在幾個(gè)核心架構(gòu)基礎(chǔ)之上的開(kāi)發(fā)者數(shù)據(jù)平臺(tái),使您能夠滿足現(xiàn)代應(yīng)用程序的需求。它讓您能夠以最佳方式進(jìn)行創(chuàng)新,構(gòu)建事務(wù)性、操作性和分析性應(yīng)用程序。本章將特別強(qiáng)調(diào)兩個(gè)關(guān)鍵元素:復(fù)制和分片,來(lái)審視 MongoDB 的架構(gòu)。

復(fù)制是 MongoDB 分布式架構(gòu)中的關(guān)鍵組成部分,確保數(shù)據(jù)的可訪問(wèn)性和對(duì)故障的韌性。它使您能夠?qū)⑾嗤臄?shù)據(jù)集分布在不同的數(shù)據(jù)庫(kù)服務(wù)器上,防止單個(gè)服務(wù)器的故障。

此外,您還將了解到分片,這是一種將數(shù)據(jù)分布在多臺(tái)機(jī)器上的水平擴(kuò)展策略。隨著應(yīng)用程序的普及和它們產(chǎn)生的數(shù)據(jù)量增加,跨機(jī)器擴(kuò)展變得至關(guān)重要,以確保足夠的讀寫(xiě)吞吐量。

本章將涵蓋以下主題:

  • 復(fù)制和分片如何提高可靠性和可用性。
  • MongoDB 中復(fù)制和分片的各種方法。
  • MongoDB 7.0 中新的分片集群特性。
  • 復(fù)制與分片的比較。

人們經(jīng)常將復(fù)制與分片混淆。雖然兩者都是數(shù)據(jù)庫(kù)管理中使用的系統(tǒng)集,但它們服務(wù)于不同的目的,并因不同的原因而使用。復(fù)制是一個(gè)數(shù)據(jù)被復(fù)制并存儲(chǔ)在多個(gè)位置以確保冗余和可靠性的過(guò)程,在數(shù)據(jù)保護(hù)和可訪問(wèn)性中扮演著至關(guān)重要的角色。

另一方面,分片涉及將較大的數(shù)據(jù)庫(kù)劃分為更小、更易于管理的部分,稱(chēng)為分片。每個(gè)分片在單獨(dú)的數(shù)據(jù)庫(kù)服務(wù)器實(shí)例上存儲(chǔ)數(shù)據(jù)集的一部分。然而,需要注意的是,每個(gè)分片還必須實(shí)現(xiàn)復(fù)制以維護(hù)數(shù)據(jù)的完整性和可用性。

結(jié)合分片和復(fù)制的目標(biāo)是確保數(shù)據(jù)的持久性和高可用性。當(dāng)分片的服務(wù)器實(shí)例失敗,且該分片上只有單個(gè)數(shù)據(jù)副本時(shí),可能會(huì)導(dǎo)致數(shù)據(jù)不可用,直到服務(wù)器恢復(fù)或更換為止。通過(guò)在每個(gè)分片內(nèi)采用復(fù)制,分片集群可以保持?jǐn)?shù)據(jù)可用性,并防止服務(wù)器故障引起的任何中斷。這種方法使分片集群能夠在不停機(jī)的情況下進(jìn)行滾動(dòng)升級(jí),允許平穩(wěn)且不間斷的系統(tǒng)維護(hù)。

接下來(lái)的幾節(jié)將深入探討復(fù)制和分片及其各自的組件。

復(fù)制 在 MongoDB 中,副本集是指維護(hù)相同數(shù)據(jù)集的一組 mongod 進(jìn)程。它們提供冗余和高可用性,是所有生產(chǎn)實(shí)施的基礎(chǔ)。通過(guò)在多個(gè)數(shù)據(jù)庫(kù)服務(wù)器上擁有多個(gè)數(shù)據(jù)副本,復(fù)制確保了一定程度的容錯(cuò)能力,保護(hù)免受單個(gè)數(shù)據(jù)庫(kù)服務(wù)器故障的影響。


圖 2.1:一個(gè)副本集

主節(jié)點(diǎn)處理所有寫(xiě)操作,并將所有數(shù)據(jù)集更改記錄在其操作日志(oplog)中。MongoDB 副本集只能有一個(gè)主節(jié)點(diǎn)。

輔助節(jié)點(diǎn)復(fù)制主節(jié)點(diǎn)的 oplog,并在自己的數(shù)據(jù)集上實(shí)現(xiàn)操作,確保它們鏡像主節(jié)點(diǎn)的數(shù)據(jù)集。如果主節(jié)點(diǎn)變得不可訪問(wèn),一個(gè)合格的輔助節(jié)點(diǎn)將啟動(dòng)選舉成為新的主節(jié)點(diǎn)。

通過(guò)在多個(gè)服務(wù)器上存儲(chǔ)數(shù)據(jù),復(fù)制提高了系統(tǒng)的可靠性。此外,支持滾動(dòng)升級(jí)允許您在不中斷的情況下升級(jí)單個(gè)服務(wù)器的軟件或硬件,確保數(shù)據(jù)庫(kù)的持續(xù)可用性。復(fù)制顯著提高了讀取密集型應(yīng)用程序的性能,將讀取負(fù)載分布在多個(gè)服務(wù)器上,以確??焖俚臄?shù)據(jù)檢索。

副本集選舉 MongoDB 使用建立在 Raft 共識(shí)算法之上的協(xié)議來(lái)協(xié)調(diào)副本集選舉,確保分布式系統(tǒng)的數(shù)據(jù)一致性。該協(xié)議包括副本集用于選擇哪個(gè)成員將承擔(dān)主角色的投票機(jī)制。

可以啟動(dòng)選舉的幾個(gè)事件包括:

  • 向副本集添加或刪除節(jié)點(diǎn)
  • 初始化副本集
  • 任何輔助節(jié)點(diǎn)和主節(jié)點(diǎn)之間的心跳故障超過(guò)預(yù)設(shè)的超時(shí)持續(xù)時(shí)間(默認(rèn)情況下,自托管主機(jī)為 10 秒,MongoDB Atlas 為 5 秒)

您的應(yīng)用程序的連接處理邏輯應(yīng)該設(shè)計(jì)得能夠考慮自動(dòng)故障轉(zhuǎn)移和隨后的選舉。MongoDB 驅(qū)動(dòng)程序有能力識(shí)別主節(jié)點(diǎn)的丟失,并自動(dòng)重試特定的讀取或?qū)懭氩僮?,為選舉提供了額外的內(nèi)置韌性層。

當(dāng)主副本變得不可用時(shí),輔助副本會(huì)為新的主節(jié)點(diǎn)投票。具有最近寫(xiě)入時(shí)間戳的副本更有可能贏得選舉。這種策略最小化了先前的主節(jié)點(diǎn)重新加入集時(shí)的回滾機(jī)會(huì)。選舉后,節(jié)點(diǎn)進(jìn)入凍結(jié)期,在這期間它們不能啟動(dòng)另一次選舉。這是為了防止連續(xù)、快速的選舉,這可能會(huì)破壞系統(tǒng)的穩(wěn)定性。目前,MongoDB 副本集僅支持稱(chēng)為協(xié)議版本 1(pv1)的協(xié)議。


圖 2.2:選舉新的主節(jié)點(diǎn)

副本集在選舉成功結(jié)束之前無(wú)法執(zhí)行寫(xiě)操作。然而,如果它們被配置為針對(duì)輔助節(jié)點(diǎn),副本集仍然可以處理讀取操作。

在正常情況下,默認(rèn)副本集配置設(shè)置下,集群選舉新主節(jié)點(diǎn)所需的平均時(shí)間不應(yīng)超過(guò) 12 秒。這個(gè)持續(xù)時(shí)間包括宣布主節(jié)點(diǎn)不可訪問(wèn)所需的時(shí)間,以及啟動(dòng)和完成選舉所需的時(shí)間??梢酝ㄟ^(guò)更改設(shè)置來(lái)調(diào)整這個(gè)時(shí)間框架。選舉超時(shí)配置選項(xiàng)
settings.electionTimeoutMillis 可以調(diào)整這個(gè)時(shí)間。

成員優(yōu)先級(jí):一旦建立了穩(wěn)定的主節(jié)點(diǎn),選舉算法允許最高優(yōu)先級(jí)的輔助節(jié)點(diǎn)啟動(dòng)選舉。成員優(yōu)先級(jí)影響選舉的時(shí)機(jī)和結(jié)果,優(yōu)先級(jí)更高的輔助節(jié)點(diǎn)可能會(huì)更早地啟動(dòng)選舉并獲勝。然而,盡管有優(yōu)先級(jí)更高的成員可用,優(yōu)先級(jí)較低的成員可能會(huì)短暫地?fù)?dān)任主節(jié)點(diǎn)。選舉過(guò)程持續(xù)進(jìn)行,直到最高優(yōu)先級(jí)的成員成為主節(jié)點(diǎn)。優(yōu)先級(jí)值為 0 的成員不能成為主節(jié)點(diǎn),也不尋求選舉。

由于副本集最多可以容納 50 名成員,其中只有 7 名是投票成員,包括非投票成員可以使集超過(guò) 7 名的限制。非投票成員的特征是擁有零票,必須具有優(yōu)先級(jí)為 0。

副本集 oplog:oplog 是一個(gè)獨(dú)特的固定集合,它維護(hù)了一個(gè)連續(xù)的日志,記錄了所有改變 MongoDB 數(shù)據(jù)庫(kù)中數(shù)據(jù)的操作。它可以擴(kuò)展超過(guò)其設(shè)置的大小限制,以防止刪除大多數(shù)提交點(diǎn)。

MongoD 中的寫(xiě)操作在主節(jié)點(diǎn)上執(zhí)行,隨后記錄在主節(jié)點(diǎn)的 oplog 中。輔助成員異步復(fù)制并應(yīng)用這些操作。副本集的所有成員都持有 oplog 的副本,位于 local.oplog.rs 集合中,使它們能夠跟上數(shù)據(jù)庫(kù)的當(dāng)前狀態(tài)。

為了支持復(fù)制,副本集的所有成員都相互交換心跳(ping)。任何輔助成員都可以從任何其他成員導(dǎo)入 oplog 條目。oplog 中的每個(gè)操作都是冪等的,這意味著無(wú)論對(duì)目標(biāo)數(shù)據(jù)集應(yīng)用一次還是多次,oplog 操作都會(huì)產(chǎn)生相同的結(jié)果。

oplog 窗口:Oplog 條目帶有時(shí)間戳。oplog 窗口指的是 oplog 中最近和最早時(shí)間戳之間的時(shí)間間隔。如果輔助節(jié)點(diǎn)與主節(jié)點(diǎn)失去連接,只有在重新建立連接的時(shí)間在 oplog 窗口的持續(xù)時(shí)間內(nèi),它才能使用復(fù)制重新同步。MongoDB 允許定義保留 oplog 條目的最小持續(xù)時(shí)間(以小時(shí)為單位),以及特定大小。系統(tǒng)僅在以下條件下才會(huì)丟棄 oplog 條目:

  • oplog 已填滿到其最大配置容量,并且 oplog 條目已超過(guò)基于主機(jī)系統(tǒng)時(shí)鐘指定的保留期限。
  • 沒(méi)有指定的最小 oplog 保留期限,MongoDB 默認(rèn)采用其標(biāo)準(zhǔn)行為。它從最舊的條目開(kāi)始截?cái)?oplog,確保 oplog 不超過(guò)配置的最大大小。

副本集部署架構(gòu):生產(chǎn)系統(tǒng)的標(biāo)準(zhǔn)部署涉及一個(gè)三成員的副本集。這些集提供了冗余和對(duì)故障的韌性。雖然建議避免不必要的復(fù)雜性,但架構(gòu)最終應(yīng)由應(yīng)用程序的需求指導(dǎo)。通常,應(yīng)遵循以下規(guī)則:

  • 確保副本集具有奇數(shù)個(gè)投票成員,以防止網(wǎng)絡(luò)分區(qū)期間的分裂決策,使更大的部分可以接受寫(xiě)入。
  • 如果您的投票成員集是偶數(shù),請(qǐng)考慮添加另一個(gè)攜帶數(shù)據(jù)的投票成員。如果限制阻止了這一點(diǎn),請(qǐng)引入一個(gè)仲裁者。
  • 包含隱藏或延遲的成員以支持專(zhuān)用功能,如備份或報(bào)告。
  • 為了在數(shù)據(jù)中心故障的情況下保護(hù)您的數(shù)據(jù),請(qǐng)確保至少有一個(gè)成員位于備用數(shù)據(jù)中心。

副本集仲裁者:在您擁有一個(gè)主節(jié)點(diǎn)和一個(gè)輔助節(jié)點(diǎn),但預(yù)算限制阻止您添加另一個(gè)輔助節(jié)點(diǎn)的情況下,您可以將仲裁者納入您的副本集。仲裁者參與主節(jié)點(diǎn)選舉,但它不持有數(shù)據(jù)集的副本,也無(wú)法成為主節(jié)點(diǎn)。仲裁者在選舉中攜帶一票。默認(rèn)情況下,其優(yōu)先級(jí)設(shè)置為0。

隱藏的副本集成員:隱藏成員構(gòu)成副本集的一個(gè)重要部分;然而,它們不能擔(dān)任主節(jié)點(diǎn)角色,并且在客戶端應(yīng)用程序中不可見(jiàn)。盡管不可見(jiàn),隱藏成員仍然能夠參與并投票選舉。隱藏節(jié)點(diǎn)可以作為專(zhuān)用副本集成員,用于執(zhí)行備份操作或運(yùn)行某些報(bào)告查詢(xún)。要設(shè)置一個(gè)隱藏節(jié)點(diǎn)并防止成員被提升為主節(jié)點(diǎn),您可以將其優(yōu)先級(jí)設(shè)置為0,并將隱藏參數(shù)配置為true,如下例所示:

cfg = rs.conf()
cfg.members[n].hidden = true
cfg.members[n].priority = 0
rs.reconfig(cfg)

延遲的副本集成員延遲成員也是隱藏成員,它們以故意的延遲從源oplog復(fù)制和應(yīng)用操作,代表集群的先前狀態(tài)。例如,如果當(dāng)前時(shí)間是08:01,并且一個(gè)成員的延遲設(shè)置為一小時(shí),那么延遲成員上的最新操作不會(huì)晚于07:01:

cfg = rs.conf()
cfg.members[n].hidden = true
cfg.members[n].priority = 0
cfg.members[0].secondaryDelaySecs = 3600
rs.reconfig(cfg)

延遲成員充當(dāng)持續(xù)的備份或數(shù)據(jù)集的實(shí)時(shí)歷史記錄,為防止人為錯(cuò)誤提供安全網(wǎng)。例如,它們可以促進(jìn)從失敗的應(yīng)用程序更新和操作員錯(cuò)誤中恢復(fù),如意外刪除數(shù)據(jù)庫(kù)和集合。

寫(xiě)入關(guān)注 寫(xiě)入關(guān)注確定MongoDB在副本集上確認(rèn)寫(xiě)入操作的方式。它提供了一種機(jī)制,以確保在確認(rèn)寫(xiě)入操作之前,數(shù)據(jù)被寫(xiě)入指定數(shù)量的節(jié)點(diǎn)。

寫(xiě)入關(guān)注的組成部分 以下字段可以包含在寫(xiě)入關(guān)注中:

{ w: <value>, j: <boolean>, wtimeout: <number> }
  • w:指定必須確認(rèn)寫(xiě)入的副本集成員的所需數(shù)量。以下w: <value>寫(xiě)入關(guān)注可用:0:無(wú)需確認(rèn)。這提供了最少的持久性,但最高的性能。1:來(lái)自主節(jié)點(diǎn)的確認(rèn)。majority:來(lái)自大多數(shù)副本集成員的確認(rèn)。從MongoDB 5.0起,默認(rèn)值;之前,默認(rèn)值為1。<number>:來(lái)自特定數(shù)量的副本集成員的確認(rèn)。
  • j:請(qǐng)求確認(rèn)寫(xiě)入操作已被寫(xiě)入磁盤(pán)上的日志。如果設(shè)置為true,寫(xiě)入操作將等待日志確認(rèn)。
  • wtimeout:設(shè)置寫(xiě)入關(guān)注的時(shí)間限制,以毫秒為單位。如果在這段時(shí)間內(nèi)未達(dá)到指定的確認(rèn)級(jí)別,寫(xiě)入操作將返回錯(cuò)誤。這個(gè)錯(cuò)誤并不意味著寫(xiě)入不會(huì)完成或被回滾;它防止寫(xiě)入超過(guò)指定的閾值阻塞。

從MongoDB 4.4開(kāi)始,副本集和分片集群都有能力建立全局默認(rèn)寫(xiě)入關(guān)注。任何未定義特定寫(xiě)入關(guān)注的操作都將自動(dòng)采用此全局默認(rèn)寫(xiě)入關(guān)注的設(shè)置。使用管理命令setDefaultRWConcern來(lái)建立全局默認(rèn)配置,用于讀取或?qū)懭腙P(guān)注:

db.adminCommand({
    setDefaultRWConcern : 1,
    defaultReadConcern: { <read concern> },
    defaultWriteConcern: { <write concern> },
    writeConcern: { <write concern> },
    comment: <any>
})

從MongoDB 5.0起,默認(rèn)寫(xiě)入關(guān)注設(shè)置為 { w: "majority" }。然而,當(dāng)部署包括仲裁者時(shí),有例外:

  • 投票多數(shù)被計(jì)算為投票成員數(shù)量的一半加1,向下取整。如果承載數(shù)據(jù)的投票成員數(shù)不超過(guò)這個(gè)投票多數(shù),則默認(rèn)寫(xiě)入關(guān)注調(diào)整為 { w: 1 }。
  • 在任何其他情況下,默認(rèn)寫(xiě)入關(guān)注保持為 { w: "majority" }。

寫(xiě)入關(guān)注的重要性 寫(xiě)入關(guān)注的選擇可以影響數(shù)據(jù)的性能和持久性:

  • 性能:較低的寫(xiě)入關(guān)注(例如,w: 0)可以通過(guò)減少寫(xiě)入操作的延遲來(lái)提高性能。然而,它冒著數(shù)據(jù)持久性的風(fēng)險(xiǎn)。
  • 持久性:較高的寫(xiě)入關(guān)注(例如,w: "majority")通過(guò)等待大多數(shù)節(jié)點(diǎn)的確認(rèn)來(lái)確保數(shù)據(jù)的持久性。這可能會(huì)在寫(xiě)入操作中引入輕微的延遲。

讀取偏好 在MongoDB中,讀取偏好確定MongoDB客戶端如何將讀取操作路由到副本集的成員。默認(rèn)情況下,MongoDB將所有讀取操作定向到主成員。然而,通過(guò)調(diào)整讀取偏好,可以將讀取負(fù)載分布到輔助成員,提高系統(tǒng)的整體性能和可用性。

讀取偏好的組成部分 MongoDB支持五種讀取偏好模式:

  • primary:所有讀取操作都定向到主成員(默認(rèn))。
  • primaryPreferred:如果可用,讀取定向到主成員;否則,它們被路由到輔助成員。
  • secondary:所有讀取操作都定向到輔助成員。
  • secondaryPreferred:如果有任何可用的輔助成員,讀取定向到輔助成員;否則,它們被路由到主成員。
  • nearest:讀取操作定向到網(wǎng)絡(luò)延遲最低的成員,無(wú)論成員的狀態(tài)如何。

除了讀取偏好模式,您還可以指定以下選項(xiàng):

  • 標(biāo)簽集:標(biāo)簽集允許通過(guò)將自定義標(biāo)簽與副本集成員關(guān)聯(lián)來(lái)定制讀取偏好。然后,客戶端可以將讀取操作定向到具有特定標(biāo)簽的成員。
  • 最大陳舊度:陳舊度指的是從主節(jié)點(diǎn)到輔助節(jié)點(diǎn)的復(fù)制延遲。此選項(xiàng)指定輔助成員在客戶端停止將其用于讀取操作之前可以有多陳舊。

讀取偏好的重要性 讀取偏好的選擇可以影響數(shù)據(jù)的性能和可用性:

  • 性能:將讀取操作分布到輔助成員可以通過(guò)減少主節(jié)點(diǎn)的負(fù)載來(lái)提高性能。
  • 可用性:如果主節(jié)點(diǎn)不可用,如果讀取偏好模式允許,讀取操作仍可由輔助成員提供。

讀取關(guān)注 讀取關(guān)注決定了從副本集和分片集群中讀取的數(shù)據(jù)的一致性和隔離屬性。通過(guò)調(diào)整讀取關(guān)注,可以控制讀取操作中數(shù)據(jù)的可見(jiàn)性,從而確保所需的一致性和隔離級(jí)別。

讀取關(guān)注的組成部分 MongoDB 支持以下讀取關(guān)注級(jí)別:

  • "local":返回在查詢(xún)開(kāi)始時(shí) MongoDB 實(shí)例可用的最新數(shù)據(jù),不考慮復(fù)制的狀態(tài)(默認(rèn))。
  • "available":返回在查詢(xún)時(shí)分布式系統(tǒng)中當(dāng)前可用的數(shù)據(jù)。這個(gè)級(jí)別提供最小的延遲,但不保證一致性。
  • "majority":返回已被大多數(shù)副本集成員確認(rèn)的數(shù)據(jù)。這確保了高水平的一致性。
  • "linearizable":提供最高級(jí)別的一致性,通過(guò)返回反映在讀取操作開(kāi)始之前完成的所有成功的大多數(shù)確認(rèn)寫(xiě)入的數(shù)據(jù)。
  • "snapshot":返回所有副本集成員的特定時(shí)間點(diǎn)的數(shù)據(jù)。

讀取關(guān)注的重要性 讀取關(guān)注的選擇可以影響數(shù)據(jù)的一致性和隔離性:

  • 一致性:更高的讀取關(guān)注級(jí)別(例如,“majority”或“l(fā)inearizable”)確保返回的數(shù)據(jù)在副本集成員之間是一致的。
  • 隔離性:通過(guò)使用“snapshot”讀取關(guān)注,可以隔離事務(wù),使其與并發(fā)寫(xiě)入隔離,確保在整個(gè)事務(wù)中數(shù)據(jù)的一致視圖。

復(fù)制方法 MongoDB Shell (mongosh) 提供了一系列 shell 輔助方法,旨在促進(jìn)與副本集的交互。它們是管理復(fù)制 MongoDB 部署的關(guān)鍵工具。讓我們檢查一些管理 MongoDB 復(fù)制所需的重要方法:

  • rs.add(): 向副本集添加成員
  • rs.addArb(): 向副本集添加仲裁者
  • rs.conf(): 顯示副本集配置文檔
  • rs.initiate(): 初始化一個(gè)新的副本集
  • rs.printReplicationInfo(): 從主節(jié)點(diǎn)的角度總結(jié)副本集的狀態(tài)
  • rs.status(): 提供一份詳細(xì)當(dāng)前副本集狀態(tài)的文檔
  • rs.reconfig(): 重新配置現(xiàn)有的副本集,覆蓋現(xiàn)有的副本集配置
  • rs.stepDown(): 觸發(fā)當(dāng)前主節(jié)點(diǎn)變成輔助節(jié)點(diǎn),觸發(fā)選舉

有關(guān)復(fù)制方法的詳細(xì)列表,請(qǐng)?jiān)L問(wèn)以下資源:復(fù)制方法

除了上述復(fù)制方法,您還可以使用復(fù)制命令進(jìn)行特定操作。例如,replSetResizeOplog 改變副本集中變量 oplog 的大小。該命令接受以下字段:

  • replSetResizeOplog: 設(shè)置為 1。
  • size: 指定 oplog 的最大大小,以 MB 為單位??梢栽O(shè)置的最小大小是 990 MB,最大是 1 PB。在 mongosh 中使用 Double() 顯式將大小轉(zhuǎn)換為雙精度浮點(diǎn)數(shù)。
  • minRetentionHours: 表示保留 oplog 條目的最小小時(shí)數(shù),小數(shù)值表示小時(shí)的分?jǐn)?shù)(例如,1.5 表示 1 小時(shí)和 30 分鐘)。該值必須等于或大于 0。值為 0 意味著 mongod 應(yīng)該從最舊的條目開(kāi)始截?cái)?oplog,以維持配置的最大 oplog 大小。
db.adminCommand({
  replSetResizeOplog: <int>,
  size: <double>,
  minRetentionHours: <double>
})

要了解更多關(guān)于復(fù)制命令的信息,請(qǐng)?jiān)L問(wèn)以下資源:復(fù)制命令

分片 MongoDB 通過(guò)分片支持水平擴(kuò)展。分片涉及將數(shù)據(jù)分布在眾多進(jìn)程中,并在管理和組織大規(guī)模數(shù)據(jù)中發(fā)揮重要作用。這種方法將較大的數(shù)據(jù)庫(kù)劃分為更小、更易管理的組件,稱(chēng)為分片。每個(gè)分片存儲(chǔ)在單獨(dú)的數(shù)據(jù)庫(kù)服務(wù)器實(shí)例上,這分散了負(fù)載并提供了有效的數(shù)據(jù)管理方法。此外,該技術(shù)允許創(chuàng)建分布式數(shù)據(jù)庫(kù)以支持地理分布的應(yīng)用程序,實(shí)現(xiàn)強(qiáng)制數(shù)據(jù)在特定區(qū)域內(nèi)居住的策略。

為什么需要分片? 考慮一個(gè)數(shù)據(jù)快速擴(kuò)展且數(shù)據(jù)庫(kù)接近其最大容量的場(chǎng)景。這種情況可能會(huì)出現(xiàn)許多挑戰(zhàn)。通常,最緊迫的問(wèn)題是性能惡化。隨著數(shù)據(jù)庫(kù)的增長(zhǎng),查詢(xún)和檢索數(shù)據(jù)所需的時(shí)間可能會(huì)顯著增加。這種減速對(duì)用戶體驗(yàn)產(chǎn)生負(fù)面影響,使應(yīng)用程序看起來(lái)緩慢或無(wú)響應(yīng)。

另一個(gè)潛在障礙是存儲(chǔ)限制。大多數(shù)系統(tǒng)都有一個(gè)它們可以有效管理的數(shù)據(jù)量上限。如果您的數(shù)據(jù)增長(zhǎng)超過(guò)了系統(tǒng)的存儲(chǔ)能力,它可能導(dǎo)致系統(tǒng)故障。在管理系統(tǒng)增長(zhǎng)方面,有兩種主要策略——垂直擴(kuò)展和水平擴(kuò)展:

  • 垂直擴(kuò)展增強(qiáng)單個(gè)服務(wù)器的容量,例如,通過(guò)升級(jí) CPU、增加 RAM 或擴(kuò)展存儲(chǔ)空間。然而,技術(shù)限制可能阻止單個(gè)機(jī)器處理某些工作負(fù)載,因?yàn)榇嬖趪?yán)格的上限。因此,垂直擴(kuò)展有實(shí)際限制。
  • 水平擴(kuò)展涉及將系統(tǒng)的數(shù)據(jù)和工作負(fù)載分散在多個(gè)服務(wù)器上,增加了所需的服務(wù)器數(shù)量。每臺(tái)機(jī)器只處理總工作負(fù)載的一部分,這可能比一臺(tái)強(qiáng)大的服務(wù)器更有效。雖然這種方法可能比投資昂貴的硬件更具成本效益,但它增加了基礎(chǔ)設(shè)施和系統(tǒng)維護(hù)的復(fù)雜性。

分片集群的關(guān)鍵元素 MongoDB 分片集群由以下關(guān)鍵元素組成:

  • Shard:這是一個(gè)存儲(chǔ)集群中部分?jǐn)?shù)據(jù)的副本集。集群可以有 1 到 n 個(gè)分片,每個(gè)分片包含整體數(shù)據(jù)的不同子集。MongoDB Atlas 根據(jù)集群層級(jí)提供不同的存儲(chǔ)容量:M10-M40 為 4 TB,M50-M60 為 8 TB,M80+ 為 14 TB。
  • mongos:作為客戶端應(yīng)用程序的查詢(xún)路由器,有效管理讀寫(xiě)操作。它將客戶端請(qǐng)求引導(dǎo)到適當(dāng)?shù)姆制?lái)自多個(gè)分片的結(jié)果匯總到一個(gè)連貫的客戶端響應(yīng)中??蛻舳伺c mongos 實(shí)例建立連接,而不是直接與單個(gè)分片建立連接。建議在生產(chǎn)部署中運(yùn)行多個(gè) mongos 實(shí)例以確保高可用性。
  • Config servers:作為副本集運(yùn)作,充當(dāng)專(zhuān)門(mén)數(shù)據(jù)庫(kù)的角色,作為分片元數(shù)據(jù)的主要存儲(chǔ)庫(kù)。這些元數(shù)據(jù)包括分片數(shù)據(jù)的狀態(tài)和結(jié)構(gòu),包括分片集合的列表和路由詳細(xì)信息等重要信息。它在實(shí)現(xiàn)集群內(nèi)高效的數(shù)據(jù)管理和查詢(xún)路由中起著至關(guān)重要的作用。

圖 2.3 展示了分片集群內(nèi)組件的交互。


圖 2.3:一個(gè)分片集群

在 MongoDB 中,數(shù)據(jù)分片發(fā)生在集合級(jí)別,這意味著集合的數(shù)據(jù)分布在集群內(nèi)的多個(gè)分片中。需要注意的是,分片集群中的每個(gè)數(shù)據(jù)庫(kù)都有自己的主分片,負(fù)責(zé)存儲(chǔ)該數(shù)據(jù)庫(kù)內(nèi)所有未分片的集合。值得一提的是,分片集群中的主分片概念與副本集中的主節(jié)點(diǎn)不同;它們服務(wù)于不同的目的,彼此之間沒(méi)有關(guān)聯(lián)。

創(chuàng)建新數(shù)據(jù)庫(kù)時(shí),由 mongos 進(jìn)程選擇主分片。它選擇集群中數(shù)據(jù)量最少的分片。listDatabases 命令返回的 totalSize 字段被用作選擇標(biāo)準(zhǔn)的一個(gè)因素。

使用 movePrimary 命令可以在初次分配后移動(dòng)主分片。movePrimary 命令最初改變集群元數(shù)據(jù)中的主分片,然后遷移所有未分片的集合到指定的分片。

微分片 在某些情況下,MongoDB 提供了一種更先進(jìn)的分片配置,稱(chēng)為微分片。與傳統(tǒng)的將每個(gè)分片分配給專(zhuān)用機(jī)器的方法不同,微分片允許通過(guò)在單個(gè)主機(jī)上共置多個(gè)分片來(lái)實(shí)現(xiàn)更細(xì)粒度的控制和資源優(yōu)化。

微分片可以是一種有效的策略,特別是當(dāng)處理每個(gè)分片的較小數(shù)據(jù)大小時(shí)。通過(guò)在單個(gè)主機(jī)上合并多個(gè)分片,可以最大化資源利用率,從而提高硬件效率。

圖 2.4:微分片配置

注意: 這種方法需要仔細(xì)的資源管理,以防止同一主機(jī)上運(yùn)行的不同MongoDB進(jìn)程之間發(fā)生沖突。每個(gè)MongoDB進(jìn)程都需要分配足夠的資源以有效運(yùn)行。在實(shí)施微分片策略時(shí),正確配置每個(gè)MongoDB進(jìn)程的緩存大小至關(guān)重要??梢酝ㄟ^(guò)設(shè)置
storage.wiredTiger.engineConfig.cacheSizeGB來(lái)調(diào)整MongoDB中WiredTiger存儲(chǔ)引擎的緩存大小。這個(gè)緩存應(yīng)該足夠大,以容納每個(gè)MongoDB進(jìn)程的工作集。如果緩存缺乏必要的空間來(lái)加載更多數(shù)據(jù),WiredTiger將從緩存中移除頁(yè)面以騰出空間。

默認(rèn)情況下,storage.wiredTiger.engineConfig.cacheSizeGB 配置為總RAM的50%,少于1GB。然而,當(dāng)在同一臺(tái)機(jī)器上運(yùn)行多個(gè)MongoDB進(jìn)程時(shí),您應(yīng)該調(diào)整此設(shè)置,以確保所有MongoDB進(jìn)程的總內(nèi)存使用量不超過(guò)可用RAM。

例如, 如果您在一臺(tái)擁有16GB RAM的機(jī)器上運(yùn)行兩個(gè)MongoDB進(jìn)程,您可以為每個(gè)進(jìn)程將
storage.wiredTiger.engineConfig.cacheSizeGB設(shè)置為25%(或4GB),而不是默認(rèn)的50%。這可以防止MongoDB進(jìn)程集體消耗超過(guò)總可用RAM的內(nèi)存,為操作系統(tǒng)和其他應(yīng)用程序留出足夠的內(nèi)存。

分片的優(yōu)勢(shì): 分片提供了幾個(gè)好處,例如:

  • 增強(qiáng)的讀寫(xiě)速度: 將數(shù)據(jù)集分布在多個(gè)分片上允許并行處理。每個(gè)額外的分片都會(huì)增加您的總吞吐量,并且良好分布的數(shù)據(jù)集可以提高查詢(xún)性能。多個(gè)分片可以同時(shí)處理查詢(xún),加快響應(yīng)時(shí)間。
  • 擴(kuò)展的存儲(chǔ)容量: 增加分片的數(shù)量可以提高您的總存儲(chǔ)量。如果一個(gè)分片可以存儲(chǔ)4TB的數(shù)據(jù),每個(gè)額外的分片就會(huì)增加另外4TB。這允許幾乎無(wú)限的存儲(chǔ)容量,隨著您數(shù)據(jù)需求的增長(zhǎng),可以實(shí)現(xiàn)可擴(kuò)展性。
  • 數(shù)據(jù)本地性: 區(qū)域分片允許數(shù)據(jù)庫(kù)分布在不同的地理位置,非常適合分布式應(yīng)用。策略可以將數(shù)據(jù)限制在特定區(qū)域內(nèi),每個(gè)區(qū)域持有一個(gè)或多個(gè)分片,提高數(shù)據(jù)管理的效率和適應(yīng)性。在區(qū)域分片中,不同的分片鍵值范圍可以與每個(gè)區(qū)域相關(guān)聯(lián),根據(jù)地理位置的相關(guān)性實(shí)現(xiàn)更快、更精確的數(shù)據(jù)訪問(wèn)。

數(shù)據(jù)分布: 在分片的MongoDB集群中,正確的數(shù)據(jù)分布對(duì)于平衡工作負(fù)載、提高性能和增強(qiáng)可擴(kuò)展性至關(guān)重要,它可以防止瓶頸并確保資源的有效利用。

分片鍵: MongoDB在集合級(jí)別執(zhí)行分片,允許您選擇要分片的集合。選擇分片鍵對(duì)于分片集群至關(guān)重要,因?yàn)椴划?dāng)?shù)倪x擇可能導(dǎo)致數(shù)據(jù)分布不均、分片之間負(fù)載分配不均衡和查詢(xún)性能下降。這些問(wèn)題可能會(huì)使某些分片過(guò)載,而其他分片則未充分利用,降低系統(tǒng)效率。在極端情況下,一個(gè)被稱(chēng)為熱分片的單個(gè)分片可能會(huì)成為瓶頸,嚴(yán)重影響集群性能。因此,選擇正確的分片鍵對(duì)于分片環(huán)境中的最優(yōu)性能至關(guān)重要。

通過(guò)使用由一個(gè)或多個(gè)文檔字段組成的分片鍵,MongoDB將集合的文檔分布在各個(gè)分片上。數(shù)據(jù)通過(guò)分解分片鍵值的范圍被劃分為不重疊的塊。目標(biāo)是在集群的分片中均勻分布這些塊,確保有效的分布。

在MongoDB的近期版本中,對(duì)分片功能進(jìn)行了顯著修改:

  • 從MongoDB 4.4開(kāi)始,分片集合中的文檔可以省略分片鍵字段。在這種情況下,這些缺失的分片鍵字段在文檔分布到分片時(shí)被視為空值。
  • 從MongoDB 4.4開(kāi)始,您可以通過(guò)向現(xiàn)有的分片鍵添加后綴字段或字段來(lái)增強(qiáng)分片鍵。
  • 在MongoDB 5.0中,您可以通過(guò)修改其分片鍵來(lái)重新分片集合。

分片策略: MongoDB支持兩種分片策略,用于在分片集群中分布數(shù)據(jù):

  • 范圍分片: 涉及根據(jù)分片鍵值將數(shù)據(jù)分割成連續(xù)的序列。具有相似分片鍵值的文檔可能位于同一個(gè)分片或塊中,有助于有效查詢(xún)連續(xù)序列。然而,不當(dāng)?shù)姆制I選擇可能會(huì)影響讀寫(xiě)性能。范圍分片是默認(rèn)方法,除非配置了哈希分片或區(qū)域的選項(xiàng)。當(dāng)分片鍵表現(xiàn)出以下特征時(shí),范圍分片最有效:
  • 高基數(shù):分片鍵的基數(shù)為平衡器可以產(chǎn)生的塊的數(shù)量設(shè)定了上限。只要可能,選擇具有高基數(shù)的分片鍵。
  • 低頻率:分片鍵的頻率表示數(shù)據(jù)中特定分片鍵值的復(fù)發(fā)率。當(dāng)大部分文檔只持有一小部分潛在的分片鍵值時(shí),容納這些文檔的塊可能會(huì)變成集群瓶頸。
  • 非單調(diào)變化值:基于逐漸增加或減少的值的分片鍵更有可能將插入操作導(dǎo)向集群內(nèi)的單個(gè)塊。
  • 哈希分片: 通過(guò)計(jì)算分片鍵字段值的哈希值,然后根據(jù)哈希分片鍵值分配每個(gè)塊的范圍。盡管一系列分片鍵在值上看起來(lái)可能很接近,但它們的哈希值不太可能落在同一個(gè)塊中。值得注意的是,哈希分片對(duì)于執(zhí)行基于范圍的操作并不高效。哈希鍵適用于具有單調(diào)變化字段的分片鍵,例如ObjectId值或時(shí)間戳。一個(gè)典型的例子是默認(rèn)的_id字段,假設(shè)它只包含ObjectId值。

MongoDB 4.4引入了使用單個(gè)哈希字段構(gòu)建復(fù)合索引的能力。要?jiǎng)?chuàng)建這樣的復(fù)合哈希索引,在索引創(chuàng)建期間,將任何單個(gè)索引鍵的值指定為哈希。復(fù)合哈希索引為復(fù)合索引中的單個(gè)字段計(jì)算哈希值;這個(gè)值連同索引中的其他字段一起用作您的分片鍵。以下是一個(gè)示例:

db.planets.createIndex({ "name":1, "_id": "hashed" })
sh.shardCollection("sample_guides.planets", { "name": 1, "_id": "hashed" })

上述命令在name字段上創(chuàng)建了一個(gè)升序的復(fù)合哈希索引,_id作為哈希字段,并分片了planets集合。

分片鍵索引: 要分片一個(gè)已填充的集合,該集合需要有一個(gè)以分片鍵開(kāi)頭的索引。然而,在分片一個(gè)空集合時(shí),如果集合還沒(méi)有為指定的分片鍵準(zhǔn)備合適的索引,MongoDB會(huì)自動(dòng)生成所需的支持索引。

塊: MongoDB將分片數(shù)據(jù)組織成不同的部分,稱(chēng)為塊或范圍(從MongoDB 5.2開(kāi)始,默認(rèn)大小為128MB;在此版本之前為64MB)。每個(gè)塊由分片鍵定義的包含下限和不包含上限所特征。這些塊包含特定分片內(nèi)一系列不間斷的分片鍵值。從MongoDB 6.1開(kāi)始,塊不再自動(dòng)分割。相反,塊僅在跨分片移動(dòng)時(shí)分割。

注意: 在MongoDB 6.1之前,當(dāng)塊大小超過(guò)最大塊大小時(shí),塊會(huì)被自動(dòng)分割器分割。

平衡器和均勻塊分布: 從MongoDB 6.0.3開(kāi)始,分片集群中的數(shù)據(jù)分布基于數(shù)據(jù)大小而非塊的數(shù)量。為了確保塊的平衡分布,一個(gè)名為平衡器的后臺(tái)進(jìn)程跟蹤每個(gè)分片上每個(gè)分片集合的數(shù)據(jù)量,并在不同分片之間移動(dòng)塊。當(dāng)特定分片上的分片集合的數(shù)據(jù)量達(dá)到特定的遷移限制時(shí),平衡器嘗試重新分配跨分片的數(shù)據(jù),目標(biāo)是在遵守區(qū)域的同時(shí)實(shí)現(xiàn)每個(gè)分片上的數(shù)據(jù)均勻分布。默認(rèn)情況下,這個(gè)平衡過(guò)程是持續(xù)活躍的。

平衡器在配置服務(wù)器副本集(CSRS)的主節(jié)點(diǎn)上運(yùn)行。對(duì)于分片集群的平衡過(guò)程對(duì)用戶和應(yīng)用層是完全透明的,盡管在執(zhí)行期間可能會(huì)觀察到輕微的性能影響。

為了減輕這種影響,平衡器嘗試:

  • 限制一個(gè)分片一次只參與一個(gè)遷移。換句話說(shuō),一個(gè)分片不能同時(shí)參與多個(gè)數(shù)據(jù)遷移。平衡器會(huì)一個(gè)接一個(gè)地執(zhí)行范圍遷移。
  • MongoDB可以執(zhí)行并行數(shù)據(jù)遷移;但是,一個(gè)分片在任何時(shí)刻僅限于參與一個(gè)遷移。在由n個(gè)分片組成的分片集群中,MongoDB可以執(zhí)行多達(dá)n/2(向下取整)的并發(fā)遷移。

當(dāng)特定分片集合的最重載分片與最輕載分片之間的數(shù)據(jù)差異達(dá)到遷移閾值時(shí),開(kāi)始一輪平衡。當(dāng)分片之間的數(shù)據(jù)差異(對(duì)于該特定集合)小于集合的已建立范圍大小的三倍時(shí),認(rèn)為集合是平衡的。如果范圍大小設(shè)置為默認(rèn)的128MB,則如果某個(gè)集合的任何兩個(gè)分片之間的數(shù)據(jù)大小差異至少為384MB,將觸發(fā)遷移。

可以為平衡器的操作設(shè)置特定時(shí)間框架,以防止其干擾生產(chǎn)流量。這稱(chēng)為平衡窗口或平衡器窗口。

塊管理: 在某些情況下,需要手動(dòng)管理塊。

  • 巨型塊(Jumbo chunks): 在MongoDB中,超過(guò)指定范圍大小并且不能由MongoDB自動(dòng)分割的塊被標(biāo)記為巨型塊。雖然MongoDB自動(dòng)管理塊分割和平衡,但在某些情況下需要手動(dòng)干預(yù)來(lái)管理巨型塊。清除巨型塊標(biāo)志的首選方法是嘗試分割塊。如果塊可以被分割,MongoDB在成功分割塊后將移除標(biāo)志??梢允褂胹h.splitAt()或sh.splitFind()方法來(lái)分割巨型塊。
  • 不可分割的塊(Indivisible chunks): 在某些情況下,MongoDB無(wú)法分割不再屬于巨型塊的塊,例如,一個(gè)包含單個(gè)分片鍵值的范圍的塊。在這種情況下,您無(wú)法分割塊以清除標(biāo)志。在這些情況下,您可以修改分片鍵(您可以重新分片集合)以使塊可分割,或者您可以手動(dòng)移除標(biāo)志。

要手動(dòng)清除標(biāo)志,在管理數(shù)據(jù)庫(kù)中,發(fā)起clearJumboFlag命令,提供分片集合的命名空間和以下任一選項(xiàng):

  • 巨型塊的邊界:
db.adminCommand({
  clearJumboFlag: "sample.customers",
  bounds: [{ "x": 5 }, { "x": 6 }]
});
  • 落在巨型塊內(nèi)的具有分片鍵和值的find文檔:
db.adminCommand({
  clearJumboFlag: "sample.customers",
  find: { "x": 5 }
});

如果集合使用哈希分片鍵,請(qǐng)避免在使用clearJumboFlag時(shí)使用find字段。對(duì)于具有哈希分片鍵的集合,使用邊界字段更為合適。

  • 預(yù)分割范圍(Pre-splitting the ranges): 在大多數(shù)情況下,分片集群將自動(dòng)生成、分割和分配數(shù)據(jù)范圍,無(wú)需手動(dòng)監(jiān)督。然而,在某些情況下,MongoDB無(wú)法產(chǎn)生足夠的范圍,或者以能夠跟上必要吞吐量的速度分散數(shù)據(jù)。

如果您即將向新的分片集群加載大量數(shù)據(jù),預(yù)分割可以幫助從一開(kāi)始就將數(shù)據(jù)均勻分布在各個(gè)分片上。這可以防止單個(gè)分片成為瓶頸。

注意: 建議僅對(duì)當(dāng)前為空的集合預(yù)分割范圍。嘗試為已經(jīng)包含數(shù)據(jù)的集合手動(dòng)分割范圍可能導(dǎo)致不規(guī)則的范圍邊界和大小,并且也可能導(dǎo)致平衡行為運(yùn)行效率低下或根本不運(yùn)行。

要手動(dòng)分割空范圍,可以使用分割命令。該命令將分片集群中的一個(gè)塊分割成兩個(gè)單獨(dú)的塊。分割命令必須在管理數(shù)據(jù)庫(kù)中執(zhí)行。

讓我們來(lái)看一個(gè)例子。假設(shè)您有一個(gè)名為myapp.products的集合,您希望根據(jù)指定的分割點(diǎn)將范圍預(yù)分割為四個(gè)不同的價(jià)格類(lèi)別。分片鍵設(shè)置在價(jià)格字段上??梢允褂靡韵麓a在mongosh中實(shí)現(xiàn):

// 根據(jù)指定的分割點(diǎn)將集合分割為塊
var splitPoints = [20, 50, 100];
// 注意:'split'命令可以采用middle、find或bounds作為選項(xiàng)。
// 在這個(gè)例子中,您使用middle選項(xiàng)來(lái)指定分割點(diǎn)。
for(var i = 0; i < splitPoints.length; i++) {
  db.adminCommand({
    split: "myapp.products",
    middle: {
      price: splitPoints[i]
    }
  });
}

這段代碼將數(shù)據(jù)分為四個(gè)價(jià)格類(lèi)別:

  • 價(jià)格低于20美元的產(chǎn)品
  • 價(jià)格在20至50美元之間的產(chǎn)品
  • 價(jià)格在50至100美元之間的產(chǎn)品
  • 價(jià)格超過(guò)100美元的產(chǎn)品

從MongoDB 6.0開(kāi)始,平衡器根據(jù)數(shù)據(jù)大小在分片之間分配數(shù)據(jù)。僅僅分割范圍可能無(wú)法確保數(shù)據(jù)在分片之間均勻分布。因此,您必須手動(dòng)移動(dòng)塊以確保平衡分布:

// 您希望將塊移動(dòng)到的分片列表
var shards = ["shard0000", "shard0001", "shard0002", "shard0003"];
for (var i = 0; i < splitPoints.length; i++) {  
  var lowerBound = { price: MinKey };
  if (i > 0) {
    lowerBound = { price: splitPoints[i-1] };
  }
  
  var upperBound = { price: MaxKey };
  if (i < splitPoints.length - 1) {
    upperBound = { price: splitPoints[i] };
  }
  
  // 手動(dòng)將塊移動(dòng)到所需的分片
  db.adminCommand({ 
    moveChunk: "myapp.products", 
    find: lowerBound, 
    to: shards[i], 
    bounds: [lowerBound, upperBound] 
  });
}

這種方法有助于從一開(kāi)始就在分片之間均勻分配數(shù)據(jù)。

查詢(xún)分片數(shù)據(jù): 查詢(xún)MongoDB分片集群中的數(shù)據(jù)與在單服務(wù)器部署或副本集中查詢(xún)數(shù)據(jù)不同。您不是連接到單個(gè)服務(wù)器或副本集的主節(jié)點(diǎn),而是連接到mongos,它充當(dāng)查詢(xún)路由器并決定向哪個(gè)分片請(qǐng)求數(shù)據(jù)。在下一節(jié)中,您將探索mongos路由器的工作原理。

mongos路由器: mongos實(shí)例提供對(duì)您的MongoDB集群的唯一接口和入口點(diǎn)。應(yīng)用程序連接到mongos而不是直接連接到底層的分片。mongos執(zhí)行查詢(xún),收集結(jié)果,并將它們傳遞給應(yīng)用程序。mongos進(jìn)程不持有任何持久狀態(tài),通常也不會(huì)使用大量的系統(tǒng)資源。它作為請(qǐng)求的代理。當(dāng)查詢(xún)進(jìn)來(lái)時(shí),mongos檢查它,決定需要在哪些分片上執(zhí)行查詢(xún),并在所有目標(biāo)分片上建立游標(biāo)。

find: 如果查詢(xún)包含分片鍵或分片鍵的前綴,mongos將執(zhí)行針對(duì)性操作,只查詢(xún)包含您要查找的鍵的分片。

假設(shè)用戶集合的復(fù)合分片鍵是_id, email, country:

db.user.find({ _id: 1 })
db.user.find({ _id: 1, "email": "packt@packt.com" })
db.user.find({ _id: 1, "email": "packt@packt.com" , "country": "UK" })

這些查詢(xún)包含前綴(前兩個(gè)查詢(xún)的情況)或完整的分片鍵。另一方面,對(duì){ email, country }或{ country }的查詢(xún)將無(wú)法定位正確的分片,導(dǎo)致廣播操作。廣播操作是任何不包含分片鍵或分片鍵前綴的操作,導(dǎo)致mongos查詢(xún)每個(gè)分片。它們也稱(chēng)為散布-收集操作或扇出查詢(xún)。

sort(), limit(), 和 skip(): 如果您想對(duì)結(jié)果進(jìn)行排序,您有兩種選擇:

  • 如果您在排序條件中使用分片鍵,那么mongos可以確定它必須以何種順序查詢(xún)一個(gè)或多個(gè)分片。這導(dǎo)致了一個(gè)高效和有針對(duì)性的操作。
  • 如果您在排序條件中不使用分片鍵,那么就像沒(méi)有任何排序條件的查詢(xún)一樣,它將是一個(gè)扇出查詢(xún)。當(dāng)您在不使用分片鍵的情況下對(duì)結(jié)果進(jìn)行排序時(shí),主分片在將排序后的結(jié)果集傳遞給mongos之前,會(huì)在本地執(zhí)行分布式合并排序。

查詢(xún)的limit在每個(gè)單獨(dú)的分片上強(qiáng)制執(zhí)行,然后在mongos級(jí)別再次執(zhí)行,因?yàn)榭赡苡衼?lái)自多個(gè)分片的結(jié)果。另一方面,skip運(yùn)算符不能傳遞給單個(gè)分片,并將由mongos在檢索所有結(jié)果后本地應(yīng)用。

如果您組合使用skip()和limit()游標(biāo)方法,mongos將通過(guò)將兩個(gè)值傳遞給單個(gè)分片來(lái)優(yōu)化查詢(xún)。這在分頁(yè)等情況下特別有用。如果您在沒(méi)有sort()的情況下進(jìn)行查詢(xún),并且結(jié)果來(lái)自多個(gè)分片,mongos將為結(jié)果在分片之間進(jìn)行輪詢(xún)。

更新和刪除 從MongoDB 7.0開(kāi)始,文檔修改操作(如更新和刪除)的處理流程已被簡(jiǎn)化。如果修改操作中的find()部分包含分片鍵,mongos可以繼續(xù)將查詢(xún)路由到適當(dāng)?shù)姆制?。然而,如果find部分中缺少分片鍵,它不再像早期版本那樣觸發(fā)扇出操作。

對(duì)于updateOne()、deleteOne()或findAndModify()操作,不再?lài)?yán)格要求包含分片鍵或_id值??梢允褂萌魏巫侄蝸?lái)匹配文檔,類(lèi)似于非分片集合。然而,使用分片鍵進(jìn)行這些操作仍然更有效率,因?yàn)樗试S針對(duì)性查詢(xún)。

例如,在MongoDB 6.0中,您必須傳遞一個(gè)分片鍵來(lái)執(zhí)行updateOne():

db.cities.updateOne({ "city": "New York City" }, { $set: { "population" : 8500000 }});

在這個(gè)例子中,city代表分片鍵。然而,在MongoDB 7.0中,您可以在不包含過(guò)濾條件中的分片鍵的情況下運(yùn)行updateOne()操作:

db.cities.updateOne({ "population" : 293200 }, { $set: { "areaSize" : 211 }});

表2.3 總結(jié)了MongoDB 7.0中可用于分片的操作:

操作

描述

insert()

必須包含分片鍵

update()

可以包含分片鍵,但不是必須的

查詢(xún)帶分片鍵

針對(duì)性操作

查詢(xún)不帶分片鍵

后臺(tái)進(jìn)行散布-收集操作

索引排序,查詢(xún)帶分片鍵

針對(duì)性操作

索引排序,查詢(xún)不帶分片鍵

分布式排序合并

updateOne(), replaceOne(), deleteOne()

可以使用任何字段進(jìn)行匹配,但使用分片鍵更有效

表2.1: 分片操作

保護(hù)性讀取 從MongoDB 4.4開(kāi)始,mongos實(shí)例可以對(duì)使用非主讀取偏好的讀取操作進(jìn)行保護(hù)性讀取。mongos實(shí)例將每個(gè)查詢(xún)分片的讀取操作定向到副本集中的兩個(gè)成員,然后返回每個(gè)分片的第一個(gè)響應(yīng)結(jié)果。

支持保護(hù)性讀取的操作包括:collStats、count、dataSize、dbStats、distinct、filemd5、find、listCollections、listIndexes和planCacheListFilters。

分片方法 為了管理數(shù)據(jù)的分布,MongoDB提供了一組輔助方法。這些方法用于啟用分片、定義數(shù)據(jù)應(yīng)如何分布以及監(jiān)控分片的狀態(tài)。它們是管理分片MongoDB部署的重要工具,允許在多臺(tái)機(jī)器上高效地?cái)U(kuò)展數(shù)據(jù)。以下是各種mongosh shell輔助方法的列表:

  • sh.shardCollection()對(duì)于在MongoDB中設(shè)置分片至關(guān)重要。一旦集合被分片,MongoDB不提供方法來(lái)取消分片。但是,如果需要,稍后可以更改分片鍵。
  • db.collection.getShardDistribution()為特定分片集合提供了數(shù)據(jù)在分片上分布的詳細(xì)分解。以下是此命令顯示的輸出信息摘要:

表2.2:db.collection.getShardDistribution()的輸出信息。

輸出

類(lèi)型

描述

<shard-x>

字符串

保存分片名稱(chēng)

<host-x>

字符串

保存主機(jī)名稱(chēng)(s)

<size-x>

數(shù)字

包括數(shù)據(jù)大小,包括度量單位

<count-x>

數(shù)字

報(bào)告分片中的文檔數(shù)量

<number of chunks-x>

數(shù)字

報(bào)告分片中的塊數(shù)量

<size-x>/<number of chunks-x>

計(jì)算值

反映分片的每個(gè)塊的估計(jì)數(shù)據(jù)大小,包括度量單位

<count-x>/<number of chunks-x>

計(jì)算值

反映分片的每個(gè)塊的估計(jì)文檔數(shù)量

<stats.size>

數(shù)字

報(bào)告分片集合中數(shù)據(jù)的總大小,包括度量單位

<stats.count>

數(shù)字

報(bào)告分片集合中的總文檔數(shù)量

<calc total chunks>

計(jì)算值

報(bào)告所有分片的塊數(shù)量

<estDataPercent-x>

計(jì)算值

表示每個(gè)分片的估計(jì)數(shù)據(jù)大小占集合總數(shù)據(jù)大小的百分比

<estDocPercent-x>

計(jì)算值

反映每個(gè)分片的估計(jì)文檔數(shù)量占集合總文檔數(shù)量的百分比

  • sh.status()提供關(guān)于分片集群的信息??梢酝ㄟ^(guò)verbose參數(shù)調(diào)整輸出的詳細(xì)程度,允許提供高級(jí)概覽或詳細(xì)報(bào)告。此命令提供的信息包括分片版本、每個(gè)分片的詳細(xì)信息、活動(dòng)mongos實(shí)例的狀態(tài)、自動(dòng)分割的狀態(tài)、平衡器的狀態(tài)以及數(shù)據(jù)庫(kù)和分片集合的信息。
  • 從MongoDB 5.0開(kāi)始,sh.reshardCollection()方法使得修改集合的分片鍵以改變數(shù)據(jù)在集群中的分布成為可能。然而,在開(kāi)始重新分片操作之前,請(qǐng)確保您的應(yīng)用程序能夠承受重新分片期間可能增加延遲的兩秒寫(xiě)入阻塞。如果這是不可接受的,請(qǐng)考慮調(diào)整您的分片鍵。您的數(shù)據(jù)庫(kù)服務(wù)器還應(yīng)該擁有必要的資源:
  • 存儲(chǔ):確保每個(gè)分片上可用的存儲(chǔ)至少是將要重新分片的集合大小的2.2倍。例如,對(duì)于1TB的集合,每個(gè)分片至少應(yīng)有2.2TB的可用存儲(chǔ)。
  • 計(jì)算每個(gè)分片所需的存儲(chǔ),使用以下公式:每個(gè)分片所需的可用存儲(chǔ) = (集合存儲(chǔ)大小 * 2.2) / 集合將分布的分片數(shù)量
  • 假設(shè)一個(gè)集合占用2TB的存儲(chǔ),并且分布在四個(gè)分片上,每個(gè)分片至少需要1.1TB的可用存儲(chǔ)。
  • 示例計(jì)算:(2TB * 2.2) / 4個(gè)分片 = 1.1TB/分片
  • I/O:您的I/O容量不應(yīng)超過(guò)50%。
  • CPU使用率:保持CPU使用率低于80%。
  • sh.getBalancerState()返回一個(gè)布爾值,指示平衡器當(dāng)前是否處于活動(dòng)狀態(tài)。
  • $shardedDataDistribution,在聚合階段,返回有關(guān)分片集群中數(shù)據(jù)分布的信息。

MongoDB 7.0中的新分片集群特性

MongoDB 7.0繼續(xù)簡(jiǎn)化了分片集群的管理和理解,無(wú)論是對(duì)于運(yùn)維還是開(kāi)發(fā)用例。這個(gè)版本提供了額外的洞察力,幫助為初始和未來(lái)的分片鍵選擇做出最佳決策。此外,從MongoDB 7.0開(kāi)始,開(kāi)發(fā)者在使用這些命令時(shí)可以在分片和非分片集群上體驗(yàn)到一致的接口,同時(shí)在必要時(shí)仍然保留優(yōu)化性能的選項(xiàng)。讓我們看看MongoDB 7.0中引入的新分片特性。

分片鍵顧問(wèn)命令

由于復(fù)雜的數(shù)據(jù)模式和權(quán)衡,選擇分片鍵是一項(xiàng)復(fù)雜的任務(wù)。然而,MongoDB 7.0中的新特性旨在簡(jiǎn)化這項(xiàng)任務(wù):

  • analyzeShardKey 提供了評(píng)估候選分片鍵與現(xiàn)有數(shù)據(jù)的能力。MongoDB 7.0中的分片鍵分析提供了評(píng)估分片鍵適用性的指標(biāo),包括其唯一性(基數(shù))、頻率,以及它是否穩(wěn)定增加或減少(單調(diào)性)。此命令可以在副本集以及分片集群上運(yùn)行。
  • configureQueryAnalyzer 提供了跨集群查詢(xún)路由模式的指標(biāo),幫助發(fā)現(xiàn)負(fù)載不均衡和熱分片。它返回一個(gè)文檔,包含描述舊配置的字段(如果存在的話),以及描述新配置的字段。有了這兩個(gè)命令,可以有信心地設(shè)置初始分片鍵,或?yàn)閷?shí)時(shí)重新分片做好準(zhǔn)備,背后有確保對(duì)所選分片鍵有信心的必要數(shù)據(jù)。
  • mergeAllChunksOnShard 命令旨在整合或合并特定分片擁有的給定集合的所有可合并塊。它通過(guò)查找特定分片上的所有可合并塊,然后將它們合并,有助于解決分片維護(hù)操作期間性能下降的問(wèn)題。這可以通過(guò)減少需要在分片維護(hù)操作期間查詢(xún)的塊數(shù)量,來(lái)幫助減少碎片化并提高性能。

AutoMerger

AutoMerger是一個(gè)自動(dòng)合并符合某些可合并要求的塊的特性。此過(guò)程作為平衡操作的一部分在后臺(tái)運(yùn)行。除非被禁用,否則AutoMerger在首次啟用平衡器時(shí)啟動(dòng),并在每次運(yùn)行后暫停固定間隔(autoMergerIntervalSecs)。它在啟用時(shí)的每個(gè)間隔執(zhí)行自動(dòng)合并。對(duì)于每個(gè)集合,它確保連續(xù)合并之間的最小延遲(autoMergerThrottlingMS)。如果定義了平衡窗口,AutoMerger僅在該窗口內(nèi)運(yùn)行。在滿足以下所有條件的情況下,同一集合中的兩個(gè)或多個(gè)連續(xù)塊是可合并的:

  • 屬于同一個(gè)分片。
  • 不是巨型塊(不能參與遷移)。
  • 具有可以安全清除的遷移歷史,而不會(huì)干擾事務(wù)或快照讀取。這意味著塊的最后一次遷移至少發(fā)生在minSnapshotHistoryWindowInSeconds和transactionLifetimeLimitSeconds值之前。

您可以使用以下方法來(lái)控制AutoMerger的行為:

  • sh.startAutoMerger()
  • sh.stopAutoMerger()
  • sh.enableAutoMerger()
  • sh.disableAutoMerger()

無(wú)需分片鍵的命令支持

在分片和非分片集群上使用updateOne、deleteOne和findAndModify等命令的使用將是一致的,同時(shí)在需要時(shí)提供優(yōu)化性能的選項(xiàng)。

總結(jié)

MongoDB中的復(fù)制是一個(gè)通過(guò)在多個(gè)服務(wù)器間同步數(shù)據(jù)來(lái)提供冗余和提高數(shù)據(jù)可用性的過(guò)程。這是通過(guò)副本集實(shí)現(xiàn)的,副本集是一組維護(hù)相同數(shù)據(jù)集的MongoDB服務(wù)器。在副本集中,一個(gè)節(jié)點(diǎn)作為主節(jié)點(diǎn),接收所有寫(xiě)操作,而輔助節(jié)點(diǎn)將主節(jié)點(diǎn)的操作復(fù)制到它們自己的數(shù)據(jù)集中。這種結(jié)構(gòu)為故障轉(zhuǎn)移和恢復(fù)提供了一個(gè)健壯的系統(tǒng)。如果主節(jié)點(diǎn)失敗,輔助節(jié)點(diǎn)之間的選舉將確定一個(gè)新的主節(jié)點(diǎn),允許客戶端操作的連續(xù)性。

MongoDB中的分片是一種將數(shù)據(jù)分割和分布到多個(gè)服務(wù)器或分片上的方法。每個(gè)分片是一個(gè)獨(dú)立的副本集,并且分片共同組成一個(gè)單一的邏輯數(shù)據(jù)庫(kù)——分片集群。這種方法用于支持具有非常大數(shù)據(jù)集和高吞吐量操作的部署,有效地解決可擴(kuò)展性問(wèn)題。

責(zé)任編輯:姜華 來(lái)源: 今日頭條
相關(guān)推薦

2017-04-01 17:30:36

MongoDB分片實(shí)現(xiàn)

2023-02-14 08:01:32

2023-01-31 08:03:32

部署mongod配置

2023-10-13 08:23:05

2013-11-28 09:48:55

MongoDBSharding分片

2013-11-25 10:45:04

MongoDB

2015-05-07 15:00:41

MongoDB分片與集群NoSQL

2023-11-21 09:38:09

2013-01-29 10:45:19

MongoDB

2011-07-26 16:53:29

MongoDB數(shù)據(jù)庫(kù)自動(dòng)分片技術(shù)

2012-07-27 10:39:16

MongoDB

2011-07-28 13:24:03

MongoDBAuto-shardi

2021-08-11 06:16:27

CentOS 7 MongodbC++

2023-08-23 08:00:00

2021-05-20 06:49:45

MongoDB高可用數(shù)據(jù)庫(kù)

2020-06-01 16:05:17

MongoDB復(fù)制集數(shù)據(jù)庫(kù)

2011-04-29 13:40:37

MongoDBCommand

2019-10-11 10:52:42

Web架構(gòu)MongoDB

2012-04-19 10:04:20

ibmdw

2011-06-09 12:56:31

MongoDB
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)