一次線上事故,我頓悟了MongoDB的精髓

語言: CN / TW / HK

大家好,我是哪吒,最近專案在使用MongoDB作為圖片和文件的儲存資料庫,為啥不直接存MySQL裡,還要搭個MongoDB叢集,麻不麻煩?

讓我們一起,一探究竟,繼續學習MongoDB分片的理論與實踐,實現快速入門,豐富個人簡歷,提高面試level,給自己增加一點談資,秒變面試小達人,BAT不是夢。

三分鐘你將學會:

  1. 一次MongoDB線上事故的快速解決
  2. 什麼是MongoDB分片?
  3. MongoDB如何分片?
  4. 何時分片?
  5. 搭建MongoDB分片伺服器
  6. MongoDB如何追蹤分片叢集資料?

MongoDB拒絕連線?顯然是MongoDB服務又掛了。

連線MongoDB伺服器,一探究竟。

通過ps -aef|grep mongo檢視mongo服務是否還在?不出所料,都不在了。

大概率是因為磁碟滿了。

df -TH檢視磁碟空間。

磁碟100%如何解決?

cd到log目錄下,通過rm -rf *刪除所有日誌,再重啟MongoDB。

mongodb啟動異常:about to fork child process, waiting until server is ready for connection

由於MongoDB是叢集部署的,啟動時,會進行資料同步,可能會比較耗時,性子急的我,怎麼能忍,直接Ctrl C,強制停止,然後再重新啟動。

通過ps -aef|grep mongo檢視一下程序,兩個一樣的程序赫然在列。

通過ps -aef|grep mongo | grep -v grep | awk '{print $2}' | xargs kill -9強制停止所有mongo程序。

將data目錄下的 mongod.lock 和 diagnostic.data檔案刪掉,再重啟MongoDB,啟動指令碼mongos_start.sh(mongod --config data/mongodb.conf),完美解決。

MongoDB伺服器的部署目錄中都是什麼含義呢?它們之間又有什麼關係呢?下面簡單介紹一下MongoDB的分片。

一、什麼是MongoDB分片?

分片是指跨機器拆分資料的過程,也可以叫做分割槽。

MongoDB支援手動分割槽,使用這種方法,應用程式會維護到多個不同資料庫伺服器端的連線,每個伺服器端都是完全獨立的。應用程式不僅管理不同伺服器上不同資料的儲存,還管理在適當的伺服器上查詢資料。但當從叢集中新增或刪除節點,或者面對資料分佈或負載模式的變化時,難以維護。

MongoDB支援自動分片,這種方式試圖將資料庫架構從應用程式中抽離出來,並簡化系統管理。MongoDB自動均衡分片上的資料,使節點的新增和刪除變得更容易。

MongoDB的分片機制允許你建立一個由許多分片組成的叢集,並將集合中的資料分散在叢集中,在每個分片上放置資料的一個子集。這允許應用程式超出單機伺服器或副本集的資源限制。

分片組成的叢集對應用程式來說就像一臺單機伺服器,分片前執行一個或多個稱為mongos的路由程序,mongos維護著一個“目錄”,指明瞭每個分片包含哪些資料。應用程式可以正常連線到此路由伺服器併發出請求。路由伺服器知道哪些資料在哪個分片上,可以將請求轉發到適當的分片。如果有對請求的響應,理由伺服器會收集它們,並將它們合併,然後再返回給應用程式,對應用程式而言,它只知道自己連線到了一個單獨的mongod。

二、MongoDB如何分片?

在單臺機器上快速建立一個叢集。首先,使用--nodb--norc選項啟動mongo shellmongo --nodb --norc

使用ShardingTest類建立叢集。執行如下程式碼:

lua st = ShardingTest({ name:"one-min-shards", chunkSize:1, shards:2, rs:{ nodes:3, oplogSize:10 }, other:{ enableBalancer:true } }); - name:分片叢集的標籤; - shards:制定了叢集由兩個分片組成; - rs:將每個分片定義為一組3個節點的副本集; - enableBalancer:在叢集啟動後啟用均衡器;

ShardingTest是為了支援伺服器端測試套件設計的,它在保持儘可能低的資源佔用以及建立體系結構相對複雜的分片叢集方面,提供了很多便利。當執行ShardingTest後,它會建立一個包含兩個分片的叢集,每個分片都是一個副本集。同時會對副本集進行配置,並使用必要的選項啟動每個節點以建立複製協議。它會啟動一個mongos來管理跨分片的請求,這樣客戶端就可以像與一個獨立的mongod通訊一樣與叢集進行互動。最後,它會為用於維護理由表信心的配置伺服器啟動一個額外的副本集,以確保查詢被定向到正確的分片。

分片的主要使用場景是拆分資料集以解決硬體和成本的限制,或為應用程式提供更好的效能。

當ShardingTest完成叢集設定後,將啟動並執行10個程序,你可以連線到這些程序:兩個副本集(各有3個節點)、一個配置伺服器副本集(3個節點),以及一個mongos。預設情況下,這些程序會從20000埠開始。mongos會執行在20009埠上。

三、何時分片?

通常情況下,分片用於:

  • 增加可用RAM;
  • 增加可用磁碟空間;
  • 減少伺服器的負載;
  • 處理單個MongoDB無法承受的吞吐量;

四、搭建MongoDB分片伺服器

1、配置伺服器 config程序

配置伺服器是叢集的大腦,儲存著關於每個伺服器包含哪些資料的所有元資料,因此必須首先建立配置伺服器。配置伺服器非常重要,執行時必須啟動日誌功能,並確保它的資料儲存在非臨時性驅動器上。

配置伺服器必須在任何一個mongos程序之前通過mongod -f config.conf啟動,因為mongos需要從配置伺服器中提取配置資訊。

當對配置伺服器進行寫入時,MongoDB會使用“majority” 的 writeConcern級別; 當對配置伺服器進行讀取時,MongoDB會使用“majority” 的 readConcern級別;

這確保了分片叢集元資料在不發生回滾的情況下才會被提交到配置伺服器副本集。它還確保了只有那些不受配置伺服器故障影響的元資料才能被讀取。這可以確保所有mongos路由節點對分片叢集中的資料組織方式具有一致性。

在伺服器資源方面,配置伺服器應該具有充分的網路和CPU資源,配置伺服器只儲存了叢集中資料的目錄,因此只需要很少的硬碟儲存資源。

由於配置伺服器的重要性,在進行任何叢集維護前,都應該先對配置伺服器的資料進行備份。

2、mongos程序

mongos 是路由伺服器,供應用程式連線使用。通過mongod -f config.conf啟動路由伺服器,mongos程序需要知道配置伺服器的地址,因此需要在config.conf中配置 configdb=configReplSet/配置伺服器的三個地址,通過配置logpath,儲存MongoDB的日誌。

應該啟動一定數量的mongos程序,並儘可能將其放在靠近所有分片的位置,這樣可以提高查詢效能。

3、將副本集轉換為分片

在依次啟動配置伺服器、路由伺服器後,可以新增分片了,如果之前已經存在副本集,那麼這個副本集就會成為第一個分片。

從MongoDB 3.4 開始,對於分片叢集,分片的mongod例項必須配置 --shardsvr 選項,也就是在config.conf中新增shardsvr=true,將副本集轉換為分片的過程中,需要對副本集的每個成員都重複以上動作。

將副本集作為分片新增到集群后,就可以將應用程式的連線從副本集改為mongos路由伺服器了,並通過設定防火牆,切斷應用程式與分片的直接連線。

4、資料分片

(1)如何資料分片

假如有一個test資料庫,並在name鍵上對worker集合進行分片。

  1. 先對資料庫進行分片,> sh.enableSharding("test")
  2. 再對集合進行分片,sh.shardCollection("test.worker",{"name":1})

如果worker集合已經存在,則必須在name欄位上有索引,否則,shardCollection會返回錯誤。如果分片的集合不存在,mongos會自動在name片鍵上建立索引。

shardCollection命令會將集合拆分成多個數據塊,MongoDB會在叢集中的分片間均勻的分散集合中的資料。

五、MongoDB如何追蹤叢集資料?

1、資料塊

因為MongoDB的資料量巨大,MongoDB一般會將文件以資料塊的形式進行分組,這些資料塊是片鍵指定範圍內的文件,MongoDB一般會用一個較小的表來維護資料塊與分片之間的對映關係。

需要注意:

  1. 塊與塊之間不能重疊;
  2. 一個塊中的文件數量過大時,會自動拆分成兩個文件;
  3. 一個文件總是屬於且僅屬於一個塊;

2、塊範圍

  1. 新分片的集合中只有一個塊,塊的邊界是負無窮到正無窮;
  2. 隨著塊的增長,MongoDB會自動將其拆分成兩塊,範圍從負無窮到value,value到正無窮。範圍較小的塊包含比value小的值,範圍較大的塊包含value和比value大的值;

因此,mongos可以很容易的找到文件在哪個塊。

3、拆分塊

各個分片的主節點mongod程序會跟蹤它們當前的塊,一旦達到某個閾值,就會檢查該塊是否需要拆分,如果需要拆分,mongod就會從配置伺服器請求全域性塊大小配置值,然後執行塊拆分並更新配置伺服器上的元資料。配置伺服器會建立新的塊文件,並修改舊塊的範圍。

當客戶端寫入一個塊時,mongod會檢查該塊的拆分閾值。

如果已經達到了拆分閾值,mongod就會向均衡器傳送一個請求,將最頂部的塊進行遷移,否則該塊會留在此分片上。

因為具有相同片鍵的兩個文件一定會處於相同的塊中,所以只能在片鍵值不同的文件之間進行拆分。

下面文件如果以readTime分片,是可以的。

但是,如果我讀書讀的比較快,所有書籍在一個月的時間裡都讀完了,readTime就會是一樣的了,那就無法分片了。

因此擁有不同的片鍵值在分片時,顯得尤其重要。

{"name":"哪吒程式設計","book":"Java核心技術","readTime":"October"} {"name":"哪吒程式設計","book":"Java程式設計思想","readTime":"October"} {"name":"哪吒程式設計","book":"深入理解Java虛擬機器","readTime":"October"} {"name":"哪吒程式設計","book":"effective java","readTime":"November"} {"name":"哪吒程式設計","book":"重構 改善既有程式碼的設計","readTime":"November"} {"name":"哪吒程式設計","book":"高效能MySQL","readTime":"December"} {"name":"哪吒程式設計","book":"Spring技術內幕","readTime":"December"} {"name":"哪吒程式設計","book":"重學Java設計模式","readTime":"December"} {"name":"哪吒程式設計","book":"深入理解高併發程式設計","readTime":"January"} {"name":"哪吒程式設計","book":"Redis設計與實現","readTime":"January"}

分片的前提條件是所有的配置伺服器必須啟動並可以訪問。如果mongod不斷接到對一個塊的寫請求,則它會持續嘗試拆分該塊並失敗,而這些拆分嘗試會拖慢mongod。mongod反覆嘗試分片卻無法成功分片的過程被稱為拆分風暴

六、均衡器

均衡器負責資料的遷移。均衡器會定期檢查分片之間是否存在不均衡,如果存在,就會對塊進行遷移。在MongoDB 3.4 以上的版本上,均衡器位於配置伺服器副本集的主節點成員上。

均衡器是配置伺服器副本集主節點上的後臺程序,它會監視每個分片上的塊數量。只有當一個分片上的塊數量達到特定遷移閾值時,均衡器才會被啟用。