概述
阿裡雲資料庫MongoDB的空間使用率是一個非常重要的監控名額,如果執行個體的存儲空間完全打滿,将會直接導緻執行個體不可用。一般來說,當一個MongoDB執行個體的存儲空間使用比例達到80-85%以上時,就應及時進行處理,要麼降低資料庫實際占用空間的大小,要麼對存儲空間進行擴容,以避免空間打滿的風險。
然而,阿裡雲資料庫MongoDB的空間使用情況分析并不簡單,本文将由淺入深幫您檢視,分析和優化雲資料庫MongoDB的空間使用。
1 檢視空間使用
1.1 副本集模式
部署架構為副本集模式下,提供有多種檢視空間使用的方法,您可以根據自身需求,由淺入深了解MongoDB的空間使用情況。
1.2總體概覽
在MongoDB控制台的“基本資訊”頁中會顯示執行個體的總存儲空間使用大小,但這裡隻有目前的空間的總使用率,沒有具體的各類資料分别占用空間大小的資訊,也沒有空間使用的曆史資訊,如下圖:
1.3 監控圖分析
MongoDB副本集由多種角色組成,一個角色可能對應一個或多個實體節點。阿裡雲MongoDB對使用者暴露Primary和Secondary節點,另外還提供有隻讀執行個體的角色。可以通過點選"監控資訊",選擇對應的角色檢視MongoDB空間相關的監控情況,如下圖:
其中一個MongoDB實體節點的空間使用由兩大塊組成,分别為data_size和log_size,其中這裡的data_size是資料磁盤使用空間(不包括local庫),主要包括collection打頭的資料實體檔案,index打頭的索引實體檔案,以及少部分中繼資料實體檔案,比如WiredTiger.wt。
log_size包括local庫的實體大小,mongodb運作日志大小,以及少部分的審計日志大小。
ins_size=data_size+log_size
1.4 詳細分析
如果需要深入分析副本集中庫或表的空間詳細占用,除了MongoDB自帶的db.stats(),db.$collection_name.stats()以外,我們推薦使用阿裡雲MongoDB控制台的提供的"CloudDBA-空間分析",通過"CloudDBA-空間分析",您可以實作以下目的:
l 檢視庫表空間概覽,日均增長量,預測可用天數。
l 檢視異常庫表空間使用。
l 詳細業務表的空間使用,包括索引和資料邏輯大小,壓縮率分析,平均行長等更多内容。
更多的CloudDBA-空間分析内容參考:
https://help.aliyun.com/document_detail/162422.html更多mongodb官方提供的分析指令詳解參考:
l
https://docs.mongodb.com/manual/reference/method/db.stats/ https://docs.mongodb.com/manual/reference/method/db.collection.stats/ https://docs.mongodb.com/manual/reference/method/db.collection.storageSize/ https://docs.mongodb.com/manual/reference/method/db.collection.totalIndexSize/ https://docs.mongodb.com/manual/reference/method/db.collection.totalSize/2 分片叢集
在分片叢集的部署模式下,由于一個叢集下可能存在多個Shard,沒有整體空間使用率的概念。是以控制台不再提供"基本資訊"中的空間使用率。
2.1 監控圖分析
阿裡雲MongoDB的監控資訊中詳細提供了叢集組建mongos路由節點,config server配置節點以及shard節點的空間使用率。不過通常來說,mongos和config server節點不會成為空間瓶頸,建議選擇忽略,直接檢視各個shard中各個角色的空間使用情況,如下圖:
2.2 詳細分析
分片叢集的空間使用的詳細檢視方法與副本集模式略有不同,需要逐個登入各個shard通過指令檢視,在每個分片上的空間使用情況詳情就與副本集情況完全一樣。
另外一方面,分片叢集中的空間問題除了空間使用率以外,還存在非常大量的"各shard空間使用不均勻"問題,後者非常難以分析,目前CloudDBA暫不支援。本文後續章節會重點帶您了解和深入分析“不同分片下空間使用不均衡”,“同一副本集下各個角色空間使用不均衡”。
3 空間問題的疑難雜症分析和解決方法
3.1 空間問題上漲概要分析和一般解決思路
當收到磁盤空間報警後,一般的分析和解決思路如下:
1. 确認目前的空間使用值,确認目前空間使用中各個庫表的詳細占用情況。
2. 确認引起空間增長的主要源頭,比如是日志類增長,還是具體的某個業務表寫入暴漲。
3. 确認目前的增長是否符合預期,針對不符合預期的大量寫入場景做應用分析。
4. 确認目前的資料是否存在大量碎片,能否通過回收碎片的方式回收空間。
5. 确認是否需要做磁盤空間擴容,或者部署定時曆史資料删除或TTL Index。
6. 曆史資料大量删除完成,通過compact或者重做副本集的方式回收碎片空間。
3.2 compact方法和compact期間對執行個體的影響
compact 一個集合,會加集合所在DB的互斥寫鎖,會導緻該DB上所有的讀寫請求都阻塞,因為 compact 執行的時間可能很長,跟集合的資料量相關,是以強烈建議在業務低峰期執行,避免影響業務。
compact方法很簡單,建議優先在備庫上執行,并通過主備切換的方式來減少compact期間對業務的影響,指令為
db.runCommand({compact: "collectionName"})。
另外,MongoDB4.4以後的官方版本,Compact指令将不再阻塞業務讀寫,更多compact的指令的使用方法和限制參考:
https://docs.mongodb.com/manual/reference/command/compact/ https://mongoing.com/archives/26907 https://help.aliyun.com/document_detail/96530.html3.3 compact無效
如前文所述,在大量remove的場景下我們會需要使用compact來回收碎片空間。然而在極端場景下,compact操作雖然提示成功了,但實際上磁盤空間并沒有回收,這應該算是一個BUG或者是MongoDB在compact設計上的缺陷,并不是隻要存在碎片就一定能回收成功。compact的基本原理并不是立馬開辟新的空間存放資料來替換原來的檔案,而是将資料不斷地往前面的空間空洞挪動,是以在某些場景下雖然存在空間空洞,但内部的compact算法并不能保證肯定可以複用這些空洞。針對這種compact失效的場景,如果糾結于空間使用,可以通過重建副本的方式解決。
還有一種場景,在MongoDB3.4以前的版本,compact或許還存在一個BUG:在大量删除資料後,compact無法回收索引檔案,隻對資料檔案生效。這個可以通過使用指令db.$table_name.stats().indexSizes或者直接檢視索引實體檔案大小确認。針對這種情況,建議将核心版本更新至3.4以上。
3.4 journal log過大導緻主備空間差距巨大
在極端情況下,journal log可能觸發bug導緻空間無限上漲,可以通過MongoDB運作日志檢視到類似以下内容:
2019-08-25T09:45:16.867+0800 I NETWORK [thread1] Listener: accept() returns -1 Too many open files in system
2019-08-25T09:45:17.000+0800 I - [ftdc] Assertion: 13538:couldn't open [/proc/55692/stat] Too many open files in system src/mongo/util/processinfo_linux.cpp 74
2019-08-25T09:45:17.002+0800 W FTDC [ftdc] Uncaught exception in 'Location13538: couldn't open [/proc/55692/stat] Too many open files in system' in full-time diagnostic data capture subsystem. Shutting down the full-time diagnostic data capture subsystem.
該bug的觸發條件為主控端的open files達到設定上限,導緻MongoDB内部的log server清理線程中斷,4.0以前的官方版本均有該問題,如果有遇到您可以将核心版本更新到4.0以上,或者可以通過重新開機mongod程序臨時解決,具體的bug連結參考:
https://jira.mongodb.org/browse/WT-40833.5備庫延遲和增量備份可能導緻Secondary日志空間持續增長
預設的官方MongoDB,oplog是一個固定集合,大小基本是固定的,主備之間的實體檔案大小不會有太大差異。阿裡雲MongoDB出于oplog經常過期導緻的節點recovering狀态,開發了oplog自适應特性。也就是說,在極端場景出現主備延遲的情況下,實際oplog可以使用的大小不再受限于配置檔案定義的固定集合大小,理論上可以達到使用者申請磁盤容量的20%。這就造成了一個問題,當備庫延遲恢複後,oplog之前占用的實體空間并不會回縮。
另外,處于備份和恢複效率的考慮,阿裡雲MongoDB使用實體備份的方式在Hidden備份mongodb執行個體,期間會涉及到大量的chepoint導緻占用了更多的資料和日志空間。
針對以上場景,當空間占用量不是特别大的話通常建議直接忽略即可。也可以根據需要對oplog做單獨的compact操作,compact期間會阻塞所有的寫操作。方法如下:
db.grantRolesToUser("root", [{db: "local",role: "dbAdmin"}])
use local
db.runCommand({compact: "oplog.rs",force: true })
4 不同分片之間的空間使用不均衡
4.1 sharding key類型選擇不合理
在一個分片叢集中,片鍵類型的選擇至關重要,一般會使用hash分片或者ranged分片兩種類型。通常情況下,在磁盤均衡度方面,hash分片的政策會比ranged好很多,因為根據不同的key值,MongoDB通過内部的哈希函數可以使得資料均勻地分布在不同地分片上,如下圖所示:
而range分片一般是根據key的大小範圍進行資料分布,是以往往會造成這樣的一個現象:新插入的資料在一個熱點的chunk上,不但會引起該chunk所在的shard磁盤IO過高,也會帶來短期資料不均勻的場景。如下圖所示,所有的資料寫入chunk C所在分片,當chunk C寫滿以後會在本分片中split出新的chunk,後續通過叢集負載均衡器Balancer遷移chunk,但這個遷移需要耗費大量的時間和IO,在一個高并發寫入的場景下,資料的負載均衡速度可能跟不上資料寫入速度,進而造成分片之間資料容量不均的問題。在這種使用場景下,不建議使用range分片政策。
更多的Sharding Key類型介紹參考:
https://docs.mongodb.com/manual/core/sharding-shard-key/ https://docs.mongodb.com/manual/core/hashed-sharding/ https://docs.mongodb.com/manual/core/ranged-sharding/4.2 sharding key字段選擇不合理
通過sh.status()可以看到各個分片上的chunk數量基本一緻,但實際上絕大部分資料都隻存在部分chunk上,導緻這些熱點chunk所在的分片資料量遠大于其他分片,通過檢視MongoDB運作日志可以檢視到明顯的告警資訊:
2019-08-27T13:31:22.076+0800 W SHARDING [conn12681919] possible low cardinality key detected in superHotItemPool.haodanku_all - key is { batch: "201908260000" }
2019-08-27T13:31:22.076+0800 W SHARDING [conn12681919] possible low cardinality key detected in superHotItemPool.haodanku_all - key is { batch: "201908260200" }
2019-08-27T13:31:22.076+0800 W SHARDING [conn12681919] possible low cardinality key detected in superHotItemPool.haodanku_all - key is { batch: "201908260230" }
mongos負載均衡主要考慮的是各個shard的chunk數量保持相當,就認為資料是均衡的,是以就會出現以上的極端場景:雖然各個shard數量相當,但實際資料嚴重傾斜。因為一個chunk内shardKey幾乎完全相同但又觸發到64M的chunk分裂門檻值,這時就會分裂出一個空的chunk。久而久之,雖然chunk的數量變多了并且完成了chunk的遷移,但實際上遷移走的chunk都是空的chunk,造成了chunk數量均衡但實際資料不均衡的情況。(這應該是Balancer在遷移chunk時基于代價的考慮,認為空chunk遷移代價更低,是以優先選了空的chunk遷移)
更多split的介紹參考:
https://docs.mongodb.com/manual/core/sharding-data-partitioning/ https://docs.mongodb.com/manual/tutorial/split-chunks-in-sharded-cluster/針對這種情況,隻能在架構上重新設計,選擇合适的區分度較高的列作為sharding key。
4.3 部分db未做sharding
MongoDB分片叢集允許部分db做sharding,部分db不做shading。那麼必然會帶來這樣的一個問題:不做shading的db的資料必然隻能存在一個分片上,如果該db資料量很大,可能會造成該分片的資料量遠大于其他分片。
除了上述情況,比較容易引起該問題的使用場景通常是因為從一個源端mongos叢集導入到一個新的mongos叢集,而邏輯導入過程中忽略了一步:實作在目标端mongos叢集做好sharding設計,因為邏輯導入并不會自動做sharding設計,這一步需要事先做好。
針對這種問題,我們建議:
l 如果是因為目标叢集初始化導入,導入之前做好分片設計。
l 如果不做sharding的庫很多且資料量基本相當,Mongos提供有movePriamy指令将指定db遷移到指定分片。
l 如果存在某個db的資料量極大且未做sharding,建議對其做sharding設計或者将其拆分出來當作單一的副本集對待。
l 即使出現這種情況,如果磁盤總量足夠充裕,建議忽略。
4.4 大規模的movechunk操作可能引起分片的磁盤占用不均
movechunk的本質是向目标端shard寫入資料後remove源端資料。預設情況下,remove操作不會釋放空間,因為針對wiredTiger引擎來說每個表都有獨立的資料檔案和索引檔案,如果該檔案不删除,總的磁盤空間就不可能回縮。通常最容易引起該問題的操作為:之前的sharding叢集中未做shard設計,運作一段時間後才做了Sharding。
從原理上說movechunk引起的空間碎片和大規模delete一樣,是以針對出現大量movechunk或者remove文檔的情況,可以針對該分片進行compact操作來回收碎片空間,正常情況下compact後資料會進行重組進而回收檔案的碎片空間。
更多movechunk的介紹參考:
https://docs.mongodb.com/manual/tutorial/migrate-chunks-in-sharded-cluster/ https://docs.mongodb.com/manual/tutorial/manage-sharded-cluster-balancer/5 阿裡雲MongoDB産品在空間使用優化上的規劃
5.1計算存儲分離
目前的阿裡雲MongoDB單個實體節點最大支援的存儲空間是3T,如果單執行個體或副本集模式下的節點資料量超過3T就必須業務拆分或者更新至分片叢集,而且規格擴容涉及到資料遷移會導緻耗時較長。
阿裡雲MongoDB在副本集部署模式下即将支援雲盤以實作計算存儲分離。在雲盤存儲下,單個節點的資料存儲上限将達到數十T,以及雲原生架構帶來的分鐘級擴容能力。
5.2 ECS快照備份
在高版本的阿裡雲MongoDB執行個體中,由于oplog多線程回放技術的越發成熟,基本上不會再有備庫延遲問題,是以阿裡雲MongoDB核心層面不再對oplog做定制化改造,與官方的"固定集合"形态保持一緻,備庫延遲引起的oplog放大問題通過更新至最新版核心即可得到解決。
另外,目前阿裡雲MongoDB正在研發采用ECS快照技術備份MongoDB執行個體,當故障發生時可繞過耗時的OSS實體備份下載下傳,達到分鐘級的恢複能力。并且使用ECS快照備份後,傳統實體備份方式可能導緻Hidden節點空間上漲的問題也會得到解決。
5.3 Compact指令的核心改造優化
MongoDB4.4的Compact指令并不會阻塞讀寫,阿裡雲MongoDB在核心層面将該patch移植至雲資料庫 MongoDB 3.4及以上版本,通過DAS控制台點選的方式實作空間碎片整理的産品化。
以上内容來自于《雲資料庫運維實戰手冊》電子書,可點選
https://developer.aliyun.com/topic/download?id=8198下載下傳完整版,助力雲運維能力更上一層樓!