全面瞭解MongoDB分片指南

全面瞭解MongoDB分片指南

在當今資料驅動的世界中,資料量和資料複雜性以前所未有的速度持續增長,因此對穩健、可擴充套件的資料庫解決方案的需求變得至關重要。據估計,到 2025 年將產生 180 ZB 的資料。這些數字都是不容忽視的。

隨著資料和使用者需求的激增,依賴單一資料庫位置已變得不切實際。這會降低系統速度,讓開發人員不堪重負。您可以採用各種解決方案來優化您的資料庫,例如資料庫分片

在本綜合指南中,我們將深入探討 MongoDB 分片,揭開其優點、元件、最佳實踐、常見錯誤以及如何開始使用的神祕面紗。

什麼是資料庫分片?

資料庫分片是一種資料庫管理技術,它將不斷增長的資料庫橫向分割成更小、更易於管理的單元(稱為分片)。

隨著資料庫的擴充套件,將其劃分為多個較小的部分並將每個部分分別儲存在不同的機器上就變得非常實用。這些較小的部分或分片是整個資料庫的獨立子集。這種劃分和分發資料的過程就是資料庫分片的過程。

資料庫分片插畫

資料庫分片插畫 (圖片來源: LinkedIn)

在實施分片資料庫時,主要有兩種方法:開發定製分片解決方案或付費購買現有解決方案。這就提出了一個問題:是開發分片解決方案更合適,還是付費更合適。

構建與購買分片解決方案備忘錄圖片

構建與購買分片解決方案備忘錄圖片 (圖片來源: LinkedIn)

要做出這一選擇,您需要考慮第三方整合的成本,同時牢記以下因素:

  • 開發人員的技能和可學習性:與產品相關的學習曲線及其與開發人員技能的匹配程度。
  • 系統提供的資料模型和應用程式介面:每個資料系統都有自己的資料表示方式。將應用程式與產品整合的便利性和易用性是一個關鍵的考慮因素。
  • 客戶支援和線上文件:如果在整合過程中遇到困難或需要幫助,客戶支援的質量和可用性以及全面的線上文件就變得至關重要。
  • 雲部署的可用性:隨著越來越多的公司向雲過渡,確定第三方產品是否可以在雲環境中部署非常重要。

基於這些因素,您現在可以決定是構建一個分片解決方案,還是花錢購買一個能為您完成繁重工作的解決方案。

目前,市場上大多數資料庫都支援資料庫分片。例如,MariaDB 等關係型資料庫和 MongoDB 等 NoSQL 資料庫

什麼是 MongoDB 中的分片?

使用 NoSQL 資料庫的主要目的是為了滿足查詢和儲存大量資料的計算和儲存需求。

一般來說,MongoDB 資料庫包含大量的集合。每個集合都由各種文件組成,其中包含鍵值對形式的資料。您可以使用MongoDB分片將這個大集合拆分成多個較小的集合。這樣,MongoDB 在執行查詢時就不會對伺服器造成太大壓力。

例如,西班牙電信科技公司(Telefónica Tech)管理著全球3000多萬臺物聯網裝置。為了跟上不斷增長的裝置使用率,他們需要一個能夠彈性擴充套件和管理快速增長的資料環境的平臺。MongoDB的分片技術是他們的正確選擇,因為它最符合他們的成本和容量需求。

利用MongoDB分片技術,Telefónica Tech每秒可執行超過115,000次查詢。這相當於每秒插入30,000次資料庫,延遲不到一毫秒!

MongoDB 分片的優勢

以下是 MongoDB 分片為大規模資料帶來的一些好處:

儲存容量

我們已經看到,分片將資料分散到群集分片中。這種分佈方式可讓每個分片包含整個叢集資料的一個片段。當資料集增大時,額外的分片將增加群集的儲存容量。

讀/寫

MongoDB 將讀寫工作負載分配給分片叢集中的分片,允許每個分片處理叢集操作的子集。通過新增更多的分片,這兩種工作負載都可以在叢集中橫向擴充套件。

高可用性

將分片和配置伺服器部署為副本集可提高可用性。現在,即使一個或多個分片副本集完全不可用,分片叢集也能執行部分讀寫。

停機保護

如果一臺機器因意外停機而癱瘓,許多使用者都會受到影響。在未分片的系統中,由於整個資料庫都會宕機,因此影響是巨大的。通過 MongoDB 分片,可以控制不良使用者體驗/影響的爆炸半徑。

地理分佈和效能

複製的分片可以放置在不同的區域。這意味著可以為客戶提供低延遲的資料訪問,即把消費者請求重定向到離他們更近的分片。根據區域的資料管理策略,可以將特定分片配置到特定區域。

MongoDB 分片叢集的元件

在解釋了 MongoDB 分片叢集的概念後,讓我們深入瞭解一下組成這種叢集的各個元件。

  1. 分片
  2. 配置伺服器
  3. 查詢路由器

1. 分片

每個分片都有一個分片資料子集。從 MongoDB 3.6 開始,碎片必須作為副本集部署,以提供高可用性和冗餘。

分片叢集中的每個資料庫都有一個主分片,用於儲存該資料庫的所有未分片集合。主分割槽與副本集中的主分割槽無關。

要更改資料庫的主分割槽,可以使用 movePrimary 命令。主分割槽遷移過程可能需要很長時間才能完成。

在此期間,您不應嘗試訪問與資料庫相關的集合,直到遷移過程完成。根據遷移的資料量,該過程可能會影響整個群集的執行。

您可以使用 mongosh 中的 sh.status() 方法檢視群集概覽。該方法將返回資料庫的主分塊以及分塊間的分塊分佈。

2. 配置伺服器

將分片叢集的配置伺服器部署為副本集,可以提高整個配置伺服器的一致性。這是因為 MongoDB 可以利用標準副本集讀寫協議來讀寫配置資料。

要將配置伺服器作為副本集部署,必須執行 WiredTiger 儲存引擎。WiredTiger 在寫操作中使用文件級併發控制。因此,多個客戶端可以同時修改一個集合中的不同文件。

配置伺服器將分片叢集的後設資料儲存在配置資料庫中。要訪問配置資料庫,可以在 mongo shell 中使用以下命令:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
use config
use config
use config

這裡有幾個限制需要注意:

  • 用於配置伺服器的副本集配置應該沒有仲裁者。仲裁者參與主伺服器的選舉,但它沒有資料集副本,不能成為主伺服器。
  • 該副本集不能有任何延遲成員。延遲成員擁有副本集的資料集副本。但延遲成員的資料集包含資料集的早期或延遲狀態。
  • 您需要為配置伺服器建立索引。簡單地說,任何成員都不應將 members[n].buildIndexes 設定為 false

如果配置伺服器副本集失去了主成員且無法選出一個,群集的後設資料就會變成只讀。你仍然可以讀寫分片,但在副本集選出主成員之前,不會發生分塊或遷移。

3. 查詢路由器

MongoDB mongos 例項可以充當查詢路由器,讓客戶端應用程式和分片叢集輕鬆連線。

從 MongoDB 4.4 開始,mongos 可以支援對衝讀取,以減少延遲。有了對衝讀取功能,mongos 例項會為每個被查詢的分片向兩個副本整合員分派讀取操作。然後,它會從每個分割槽的第一個響應者那裡返回結果。

以下是這三個元件在分片叢集中的互動方式:

分片叢集元件的互動

分片叢集元件的互動(圖片來源:MongoDB Sharding

mongos 例項將通過以下方式把查詢導向一個群集:

  1. 檢查需要接收查詢的分片列表。
  2. 在所有目標分片上建立遊標。

然後,mongos 會合並來自每個目標碎片的資料,並返回結果文件。有些查詢修改器(如排序)會在 mongos 提取結果前在每個分割槽上執行。

在某些情況下,如果分片鍵或分片鍵字首是查詢的一部分,mongos 會執行預先計劃好的操作,將查詢指向群集中的分片子類。

對於生產叢集,要確保資料冗餘,系統高度可用。您可以選擇以下配置進行生產分片群集部署:

  • 將每個分片部署為 3 個成員的副本集
  • 將配置伺服器部署為 3 個成員副本集
  • 部署一個或多個 mongos 路由器

對於非生產群集,可使用以下元件部署分片群集:

  • 單個碎片副本集
  • 一個副本集配置伺服器
  • 一個 mongos 例項

MongoDB 如何進行分片?

既然我們已經討論了分片叢集的不同組成部分,那麼現在就該深入探討其流程了。

要將資料分割到多個伺服器上,需要使用 mongos。當你連線向 MongoDB 傳送查詢時,mongos 會查詢並找到資料所在的位置。然後,它會從正確的伺服器獲取資料,如果資料被分割在多個伺服器上,它還會將所有資料合併在一起。

由於這一切都將在後臺完成,因此你無需在應用程式端做任何事情。MongoDB 會像普通查詢連線一樣執行。你的客戶端將連線到 mongos,配置伺服器將處理其餘事宜。

如何逐步設定 MongoDB 分片?

設定 MongoDB 分片是一個涉及多個步驟的過程,以確保資料庫叢集的穩定和高效。下面是如何設定 MongoDB 分片的詳細分步說明。

在開始之前,需要注意的是,要在 MongoDB 中設定分片,至少需要三臺伺服器:一臺用於配置伺服器,一臺用於 mongos 例項,一臺或多臺用於分片。

  1. 從配置伺服器建立目錄
  2. 在配置模式下啟動 MongoDB
  3. 啟動 Mongos 例項
  4. 連線到 Mongos 例項
  5. 為叢集新增伺服器
  6. 啟用資料庫分片

1. 從配置伺服器建立目錄

首先,我們要為配置伺服器資料建立一個目錄。在第一臺伺服器上執行以下命令即可完成:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
mkdir /data/configdb
mkdir /data/configdb
 mkdir /data/configdb

2. 在配置模式下啟動 MongoDB

接下來,我們將使用以下命令在第一臺伺服器上以配置模式啟動 MongoDB:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
mongod --configsvr --dbpath /data/configdb --port 27019
mongod --configsvr --dbpath /data/configdb --port 27019
mongod --configsvr --dbpath /data/configdb --port 27019

這將在  port 27019 啟動配置伺服器,並將資料儲存在 /data/configdb 目錄中。請注意,我們使用 --configsvr 標誌表示該伺服器將用作配置伺服器。

3. 啟動 Mongos 例項

下一步是啟動 mongos 例項。這個過程會根據分片金鑰將查詢路由到正確的分片。要啟動 mongos 例項,請使用以下命令:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
mongos --configdb :27019
mongos --configdb :27019
mongos --configdb :27019

替換為執行配置伺服器的機器的 IP 地址或主機名。

4. 連線到 Mongos 例項

一旦執行了 mongos 例項,我們就可以使用 MongoDB shell 與之連線。執行以下命令即可實現:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
mongo --host --port 27017
mongo --host --port 27017
mongo --host  --port 27017

在該命令中,應替換為執行 mongos 例項的伺服器的主機名或 IP 地址。這將開啟 MongoDB shell,允許我們與 mongos 例項互動並向叢集新增伺服器。

替換為執行 mongos 例項的機器的 IP 地址或主機名。

5. 為叢集新增伺服器

現在我們已連線到 mongos 例項,可以通過執行以下命令將伺服器新增到群集中:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
sh.addShard(":27017")
sh.addShard(":27017")
sh.addShard(":27017")

在該命令中,應替換為執行分片的伺服器的主機名或 IP 地址。該命令將把分塊新增到群集,並使其可供使用。

對要新增到群集中的每個分塊重複此步驟。

6. 啟用資料庫分片

最後,我們將執行以下命令為資料庫啟用分片:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
sh.enableSharding("")
sh.enableSharding("")
sh.enableSharding("")

在該命令中,應替換為要分片的資料庫名稱。這將啟用指定資料庫的分片功能,允許你將其資料分佈到多個分片上。

就是這樣!按照這些步驟,你現在應該已經擁有了一個功能齊全的 MongoDB 分片叢集,可以橫向擴充套件並處理高流量負載。

MongoDB 分片最佳實踐

雖然我們已經建立了分片叢集,但定期監控和維護叢集對確保最佳效能至關重要。MongoDB 分片的一些最佳實踐包括

  1. 確定正確的分片金鑰
  2. 規劃資料增長
  3. 為分片使用專用硬體
  4. 為碎片伺服器使用複製集
  5. 監控分片效能
  6. 制定災難恢復計劃
  7. 適當時使用基於雜湊值的分片

1. 確定正確的分片金鑰

分片鍵是 MongoDB 分片中的一個關鍵因素,它決定了資料在分片間的分佈方式。選擇一個能在分片間均勻分佈資料並支援最常見查詢的分片鍵非常重要。應避免選擇會導致熱點或資料分佈不均的分片鍵,因為這會導致效能問題。

要選擇正確的分割槽金鑰,你應該分析你的資料和你要執行的查詢型別,然後選擇一個滿足這些要求的金鑰。

2. 規劃資料增長

在建立分片叢集時,要為未來的增長做好規劃,首先要有足夠的分片來處理當前的工作負載,然後再根據需要新增更多分片。確保你的硬體和網路基礎設施能夠支援分片的數量和你未來預期的資料量。

3. 為分片使用專用硬體

為每個分片使用專用硬體,以獲得最佳效能和可靠性。每個分片都應擁有自己的伺服器或虛擬機器,以便不受任何干擾地利用所有資源。

使用共享硬體會導致資源爭用和效能下降,影響整個系統的可靠性。

4. 為碎片伺服器使用複製集

為分片伺服器使用副本集可為 MongoDB 分片叢集提供高可用性和容錯性。每個副本集應該有三個或更多成員,每個成員應該駐留在單獨的物理機上。這種設定可確保分片叢集在單個伺服器或副本整合員發生故障時仍能正常執行。

5. 監控分片效能

監控分片的效能對於在問題變成大問題之前發現問題至關重要。你應該監控每個分片伺服器的 CPU、記憶體、磁碟 I/O 和網路 I/O,以確保分片能夠處理工作負載。

你可以使用 MongoDB 的內建監控工具(如 mongostatmongotop)或第三方監控工具(如 Datadog、Dynatrace 和 Zabbix)來跟蹤分片效能。

6. 制定災難恢復計劃

制定災難恢復計劃對於維護 MongoDB 分片叢集的可靠性至關重要。您應該制定災難恢復計劃,其中包括定期備份、測試備份以確保其有效性,以及在發生故障時恢復備份的計劃。

7. 適當時使用基於雜湊值的分片

當應用程式發出基於範圍的查詢時,範圍分片是有益的,因為操作可以限制在較少的分片上,主要是單個分片。要實現這一點,你需要了解你的資料和查詢模式。

雜湊分片可確保讀寫的均勻分佈。不過,它不能提供高效的基於範圍的操作。

分片處理 MongoDB 資料庫時應避免哪些常見錯誤?

MongoDB 分片是一種強大的技術,可以幫助你橫向擴充套件資料庫並將資料分佈到多個伺服器上。不過,在對 MongoDB 資料庫進行分片時,應避免幾個常見錯誤。下面是一些最常見的錯誤以及如何避免它們。

  1. 選擇錯誤的分片金鑰
  2. 嘗試更改分片金鑰的值
  3. 未能監控群集
  4. 新增新分片等待時間過長(過載)
  5. 配置伺服器不足
  6. 未能備份和還原資料
  7. 無法測試分片群集

1. 選擇錯誤的分片金鑰

在對 MongoDB 資料庫進行分片時,最關鍵的決定之一就是選擇分片金鑰。分片鍵決定了資料在分片間的分佈方式,選擇錯誤的鍵會導致資料分佈不均、熱點和效能低下。

一個常見的錯誤是,在使用基於範圍的分片而不是雜湊分片時,選擇的分片鍵值只在新文件出現時才會增加。例如,時間戳(自然)或任何以時間為最重要組成部分的東西,如 ObjectID(前四個位元組是時間戳)。

如果你選擇了分片鍵,所有的插入都將進入範圍最大的分塊。即使不斷新增新分塊,最大寫入容量也不會增加。

如果你打算擴大寫入容量,可以嘗試使用基於雜湊值的分塊金鑰,這樣既能使用相同的欄位,又能提供良好的寫入可擴充套件性。

2. 嘗試更改分片金鑰的值

對於現有文件來說,分片金鑰是不可變的,這意味著你不能更改金鑰。你可以在分片前進行某些更新,但不能在分片後進行。嘗試修改現有文件的分片鍵時,會出現以下錯誤:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
cannot modify shard key's value fieldid for collection: collectionname
cannot modify shard key's value fieldid for collection: collectionname
cannot modify shard key's value fieldid for collection: collectionname

您可以刪除並重新插入檔案來修改分塊金鑰,而不是嘗試修改它。

3. 未能監控群集

分片會給資料庫環境帶來額外的複雜性,因此必須密切監控群集。不監控群集可能會導致效能問題、資料丟失和其他問題。

為避免這種錯誤,應設定監控工具來跟蹤 CPU 使用率、記憶體使用率、磁碟空間和網路流量等關鍵指標。當超過某些閾值時,還應設定警報。

4. 新增新分割槽等待時間過長(超載)

在對 MongoDB 資料庫進行分片時,需要避免的一個常見錯誤是等待新增新分片的時間過長。當一個分片的資料或查詢量過大時,就會導致效能問題,拖慢整個叢集的執行速度。

假設你有一個由 2 個分塊組成的假想叢集,其中有 20000 個塊(5000 個塊被視為 “活動 “塊),我們需要新增第 3 個分塊。第 3 個分塊最終將儲存三分之一的活動塊(以及總塊數)。

我們面臨的挑戰是,何時分塊不再增加開銷,而是成為資產。我們需要計算將活動塊遷移到新分塊時系統會產生的負載,以及與整個系統收益相比,什麼時候可以忽略不計。

在大多數情況下,我們可以比較容易地想象到,在一組超負荷的分塊上,這組遷移需要花費更長的時間,而我們新新增的分塊則需要花費更長的時間才能跨過閾值,成為淨收益。因此,最好在必要之前主動增加容量。

可能的緩解策略包括定期監控群集,並在流量較低時主動新增新分割槽,以減少對資源的競爭。建議手動平衡目標 “熱門 “分塊(訪問量高於其他分塊),以便更快地將活動轉移到新分塊。

5. 配置伺服器不足

如果配置伺服器供應不足,就會導致效能問題和不穩定性。配置不足可能是由於 CPU、記憶體或儲存等資源分配不足造成的。

這可能導致查詢效能緩慢、超時甚至崩潰。為避免這種情況,為配置伺服器分配足夠的資源至關重要,尤其是在較大的群集中。定期監控配置伺服器的資源使用情況有助於發現資源分配不足的問題。

防止這種情況的另一種方法是為配置伺服器使用專用硬體,而不是與其他群集元件共享資源。這有助於確保配置伺服器有足夠的資源來處理其工作負載。

6. 未能備份和恢復資料

備份對於確保資料不會在故障中丟失至關重要。資料丟失的原因多種多樣,包括硬體故障、人為錯誤和惡意攻擊。

不備份和恢復資料會導致資料丟失和停機。為避免這一錯誤,您應制定備份和還原策略,包括定期備份、測試備份以及將資料還原到測試環境。

7. 未測試分片群集

在將分片叢集部署到生產環境之前,必須對其進行全面測試,以確保其能夠處理預期的負載和查詢。不測試分片群集可能會導致效能低下和崩潰。

MongoDB 分片與叢集索引:哪個對大型資料集更有效?

MongoDB 分片和聚類索引都是處理大型資料集的有效策略。但它們的目的不同。選擇正確的方法取決於應用程式的具體要求。

分片是一種水平擴充套件技術,可將資料分佈到多個節點上,是處理具有高寫入率的大型資料集的有效解決方案。它對應用是透明的,允許應用與 MongoDB 進行互動,就像與單個伺服器互動一樣。

另一方面,聚類索引允許 MongoDB 在查詢匹配到索引欄位時更高效地定位資料,從而提高了從大型資料集中檢索資料的查詢效能。那麼,哪種方法對大型資料集更有效呢?答案取決於具體的使用案例和工作負載要求。

如果應用程式需要較高的寫入和查詢吞吐量,並且需要橫向擴充套件,那麼 MongoDB 分片可能是更好的選擇。不過,如果應用程式的工作負載是讀取型的,並且需要按特定順序組織頻繁查詢的資料,那麼聚類索引可能會更有效。

分片和聚類索引都是在 MongoDB 中管理大型資料集的強大工具。關鍵是要仔細評估您的應用需求和工作負載特徵,以確定適合您的特定用例的最佳方法。

小結

分片叢集是一種功能強大的架構,可以處理大量資料並進行橫向擴充套件,以滿足不斷增長的應用需求。叢集由分片、配置伺服器、mongos 程序和客戶端應用程式組成,資料根據精心選擇的分片金鑰進行分割槽,以確保高效分發和查詢。

利用分片的強大功能,應用程式可以實現高可用性,提高效能,並有效利用硬體資源。選擇正確的分片金鑰對資料的均勻分佈至關重要。

您對 MongoDB 和資料庫分片實踐有什麼看法?您覺得我們應該介紹分片的哪些方面嗎?請在評論中告訴我們!

評論留言