一次線上事故,我頓悟了MongoDB的精髓
大家好,我是哪吒,最近項目在使用MongoDB作為圖片和文檔的存儲數據庫,為啥不直接存MySQL里,還要搭個MongoDB集群,麻不麻煩?
讓我們一起,一探究竟,繼續學習「MongoDB分片」的理論與實踐,實現快速入門,豐富個人簡歷,提升面試level,給自己增加一點談資,秒變面試小達人,BAT不是夢。
三分鐘你將學會:
- 一次MongoDB線上事故的快速解決
- 什么是MongoDB分片?
- MongoDB如何分片?
- 何時分片?
- 搭建MongoDB分片服務器
- 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 shell:mongo --nodb --norc。
使用ShardingTest類創建集群。運行如下代碼:
- 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中配置 cnotallow=configReplSet/配置服務器的三個地址,通過配置logpath,保存MongoDB的日志。
應該啟動一定數量的mongos進程,并盡可能將其放在靠近所有分片的位置,這樣可以提高查詢性能。
3、將副本集轉換為分片
在依次啟動配置服務器、路由服務器后,可以添加分片了,如果之前已經存在副本集,那么這個副本集就會成為第一個分片。
從MongoDB 3.4 開始,對于分片集群,分片的mongod實例必須配置 --shardsvr 選項,也就是在config.conf中添加shardsvr=true,將副本集轉換為分片的過程中,需要對副本集的每個成員都重復以上動作。
將副本集作為分片添加到集群后,就可以將應用程序的連接從副本集改為mongos路由服務器了,并通過設置防火墻,切斷應用程序與分片的直接連接。
4、數據分片
(1)如何數據分片
假如有一個test數據庫,并在name鍵上對worker集合進行分片。
- 先對數據庫進行分片,> sh.enableSharding("test")。
- 再對集合進行分片,sh.shardCollection("test.worker",{"name":1});。
如果worker集合已經存在,則必須在name字段上有索引,否則,shardCollection會返回錯誤。如果分片的集合不存在,mongos會自動在name片鍵上創建索引。
shardCollection命令會將集合拆分成多個數據塊,MongoDB會在集群中的分片間均勻的分散集合中的數據。
五、MongoDB如何追蹤集群數據??
1、數據塊
因為MongoDB的數據量巨大,MongoDB一般會將文檔以數據塊的形式進行分組,這些數據塊是片鍵指定范圍內的文檔,MongoDB一般會用一個較小的表來維護數據塊與分片之間的映射關系。
需要注意:
- 塊與塊之間不能重疊。
- 一個塊中的文檔數量過大時,會自動拆分成兩個文檔。
- 一個文檔總是屬于且僅屬于一個塊。
2、塊范圍
- 新分片的集合中只有一個塊,塊的邊界是負無窮到正無窮。
- 隨著塊的增長,MongoDB會自動將其拆分成兩塊,范圍從負無窮到value,value到正無窮。范圍較小的塊包含比value小的值,范圍較大的塊包含value和比value大的值。
因此,mongos可以很容易地找到文檔在哪個塊。
3、拆分塊
各個分片的主節點mongod進程會跟蹤它們當前的塊,一旦達到某個閾值,就會檢查該塊是否需要拆分,如果需要拆分,mongod就會從配置服務器請求全局塊大小配置值,然后執行塊拆分并更新配置服務器上的元數據。配置服務器會創建新的塊文檔,并修改舊塊的范圍。
當客戶端寫入一個塊時,mongod會檢查該塊的拆分閾值。
如果已經達到了拆分閾值,mongod就會向均衡器發送一個請求,將最頂部的塊進行遷移,否則該塊會留在此分片上。
因為具有相同片鍵的兩個文檔一定會處于相同的塊中,所以只能在片鍵值不同的文檔之間進行拆分。
下面文檔如果以readTime分片,是可以的。
但是,如果我讀書讀的比較快,所有書籍在一個月的時間里都讀完了,readTime就會是一樣的了,那就無法分片了。
因此擁有不同的片鍵值在分片時,顯得尤其重要。
分片的前提條件是所有的配置服務器必須啟動并可以訪問。如果mongod不斷接到對一個塊的寫請求,則它會持續嘗試拆分該塊并失敗,而這些拆分嘗試會拖慢mongod。mongod反復嘗試分片卻無法成功分片的過程被稱為「拆分風暴」。
六、均衡器?
均衡器負責數據的遷移。均衡器會定期檢查分片之間是否存在不均衡,如果存在,就會對塊進行遷移。在MongoDB 3.4 以上的版本上,均衡器位于配置服務器副本集的主節點成員上。
均衡器是配置服務器副本集主節點上的后臺進程,它會監視每個分片上的塊數量。只有當一個分片上的塊數量達到特定遷移閾值時,均衡器才會被激活。
本文轉載自微信公眾號「哪吒編程」,可以通過以下二維碼關注。轉載本文請聯系哪吒編程公眾號。