MongoDB實例空間使用率高問題
云數(shù)據(jù)庫MongoDB實例的空間使?率是?個?常重要的監(jiān)控指標(biāo)。如果MongoDB實例的空間被完全使用,將會導(dǎo)致實例不可?。本文介紹查看MongoDB實例空間使用情況的方法,以及各種空間使用情況的原因和優(yōu)化策略。
背景信息
實例空間使用率達到80%~85%以上時,可通過降低數(shù)據(jù)庫實際占用空間或擴容存儲空間的方法避免空間占滿的風(fēng)險。
查看空間使用情況
副本集架構(gòu)
當(dāng)云數(shù)據(jù)庫MongoDB實例為副本集架構(gòu)時,您可以登錄MongoDB管理控制臺通過以下方法查看空間使用情況:
總體概覽
在基本信息頁面的規(guī)格信息區(qū)域,查看當(dāng)前實例的磁盤空間和使用率。
監(jiān)控圖分析
在左側(cè)導(dǎo)航欄中單擊監(jiān)控信息,選擇目標(biāo)節(jié)點,查看目標(biāo)節(jié)點的磁盤空間使用量(Bytes)和磁盤空間使用率(%)。
云數(shù)據(jù)庫MongoDB副本集實例提供一個可供讀寫訪問的Primary節(jié)點(主節(jié)點)、一個或多個提供高可用的Secondary節(jié)點(從節(jié)點)、一個隱藏的Hidden節(jié)點(隱藏節(jié)點)和一個或多個可選的ReadOnly節(jié)點(只讀節(jié)點)。MongoDB節(jié)點的空間使用量由data_size和log_size組成,即ins_size=data_size+log_size。其中:
data_size:數(shù)據(jù)磁盤使?空間(不包括local庫),主要包括collection開頭的數(shù)據(jù)物理?件,索引開頭的索引物理?件和部分元數(shù)據(jù)物理?件,例如WiredTiger.wt。
log_size:local庫的物理??、mongodb運??志??和部分審計?志??。
詳細分析
您可以通過以下兩種方法詳細分析空間使用問題:
通過MongoDB自身提供的命令
db.stats()
和db.$collection_name.stats()
分析。在
頁面分析。您可以在
頁面查看以下配置信息:數(shù)據(jù)庫和表使用空間情況概覽、?均增?量和預(yù)測可?天數(shù)。
異常數(shù)據(jù)庫和表使用空間情況。
詳細業(yè)務(wù)表使用空間情況,包括索引文件大小、數(shù)據(jù)文件大小,壓縮率分析,平均??等。
分?集群架構(gòu)
當(dāng)云數(shù)據(jù)庫MongoDB實例為分片集群架構(gòu)時,您可以登錄MongoDB管理控制臺通過以下方法查看空間使用情況:
監(jiān)控圖分析
在監(jiān)控信息頁面,選擇目標(biāo)節(jié)點,查看目標(biāo)節(jié)點的磁盤空間使用量(Bytes)和磁盤空間使用率(%)。
詳細分析
通過云數(shù)據(jù)庫MongoDB自身提供的命令
db.stats()
和db.$collection_name.stats()
依次分析各個節(jié)點的空間使用情況。
執(zhí)行compact指令導(dǎo)致數(shù)據(jù)量過大
compact期間對實例的影響
由于compact執(zhí)?的時間與集合的數(shù)據(jù)量相關(guān),如果數(shù)據(jù)量過大,則會使compact的執(zhí)行時間很長,所以為避免影響業(yè)務(wù)的讀寫,建議在業(yè)務(wù)低峰期執(zhí)?compact。
compact?法
首先在備庫上執(zhí)行命令db.runCommand({compact:"collectionName"})
,然后進行主備切換,以減少compact期間對業(yè)務(wù)的影響。其中collectionName
為集合名稱,請根據(jù)實際情況替換。
MongoDB 4.2及以前的官方版本,compact命令會阻塞業(yè)務(wù)正常讀寫,建議您僅在沒有業(yè)務(wù)流量的Secondary節(jié)點上執(zhí)行該操作。
MongoDB 4.4及以后的官方版本,compact命令將不再阻塞業(yè)務(wù)讀寫,但是在Primary節(jié)點執(zhí)行compact命令,有可能會對實例性能產(chǎn)生影響,建議您在Secondary或Hidden節(jié)點上執(zhí)行。如果您必須要在Primary節(jié)點執(zhí)行compact命令,建議您在業(yè)務(wù)低峰期進行操作。compact命令的使用方法和限制請參見:compact、MongoDB命令詳解和回收磁盤碎片以提升磁盤利用率。
MongoDB 4.4.9以前的官方版本,正在執(zhí)行compact命令的節(jié)點會進入RECOVERING狀態(tài),如果持續(xù)時間過長,該節(jié)點會被實例探活組件認定為節(jié)點不健康從而觸發(fā)相應(yīng)的重搭操作;MongoDB 4.4.9及以后的官方版本,正在執(zhí)行compact命令的節(jié)點則會維持在SECONDARY狀態(tài)。詳細信息,請參見MongoDB官方文檔。
如果您的MongoDB實例大版本為4.4但不確定小版本是否大于4.4.9,請提交工單聯(lián)系阿里云技術(shù)支持進行確認。
compact?效
compact的基本原理并不是??開辟新的空間存放數(shù)據(jù)來替換原來的?件,?是將數(shù)據(jù)不斷地往前?的空間空洞挪動,所以在某些場景下雖然存在空間空洞,但內(nèi)部的compact算法并不能保證肯定可以復(fù)?這些空洞,我們稱之為compact無效。compact無效的場景和解決方法如下:
在完成compact后,雖然提示操作成功,但實際上磁盤空間并沒有回收,對于該場景,建議您通過重建副本的方式解決。
MongoDB 3.4以前的版本,在刪除大量數(shù)據(jù)后,compact?法回收索引文件,只對數(shù)據(jù)?件?效,對于該場景,建議您將內(nèi)核版本升級?3.4以上。您可以通過如下方法確認該場景:
執(zhí)行命令
db.$table_name.stats().indexSizes
。查看索引物理文件大小。
日志過大導(dǎo)致空間上漲
Journal Log過?導(dǎo)致主備空間差距巨?
云數(shù)據(jù)庫MongoDB 4.0以前的版本,如果宿主機的open files達到設(shè)置上限,則會使云數(shù)據(jù)庫MongoDB內(nèi)部的log server清理線程中斷,進而使Journal Log過大導(dǎo)致空間無限上漲,當(dāng)通過云數(shù)據(jù)庫MongoDB的運行日志查看到類似以下內(nèi)容時,您可以將內(nèi)核版本升級到云數(shù)據(jù)庫MongoDB 4.0以上,或者通過重啟云數(shù)據(jù)庫mongod進程進行臨時解決,詳情請參見log-server thread exit quietly on error while the mongodb process still running。
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.
備庫延遲和增量備份可能導(dǎo)致從節(jié)點?志空間持續(xù)增?
云數(shù)據(jù)庫MongoDB在出現(xiàn)主備延遲的情況下,Oplog可以使用的大小不再受限于配置文件定義的固定集合大小,理論上使得可以達到用戶申請磁盤容量的20%,但當(dāng)備庫延遲恢復(fù)后,Oplog之前占?的物理空間并不會回縮。
云數(shù)據(jù)庫MongoDB使?物理備份的?式在隱藏節(jié)點備份云數(shù)據(jù)庫MongoDB實例期間會有?量的checkpoint,進而導(dǎo)致占?了更多的數(shù)據(jù)和?志空間。
對于以上兩種場景,通過對Oplog單獨做compact操作解決,具體如下:
進行compact期間會阻塞所有的寫操作。
db.grantRolesToUser("root", [{db: "local", role: "dbAdmin"}])
use local
db.runCommand({ compact: "oplog.rs", force: true })
選擇和使用分片不合理導(dǎo)致數(shù)據(jù)分布不均衡
sharding key類型選擇不合理
在?個分?集群中,?鍵類型的選擇?關(guān)重要,?般會使?hash分?或者ranged分?兩種類型。通常情況下,在磁盤均衡度??,hash分?的策略會?ranged好很多,因為根據(jù)不同的key值,云數(shù)據(jù)庫MongoDB通過內(nèi)部的哈希函數(shù)可以使得數(shù)據(jù)均勻地分布在不同地分?上,?range分??般是根據(jù)key的??范圍進?數(shù)據(jù)分布,所以往往會造成這樣的?個現(xiàn)象:新插?的數(shù)據(jù)在?個熱點的chunk上,不但會引起該chunk所在的shard磁盤I/O過?,也會帶來短期數(shù)據(jù)不均勻的場景。
Sharding Key類型的介紹,詳情請參見sharding-shard-key、hashed-sharding和ranged-sharding。
sharding key字段選擇不合理
各個分?上的chunk數(shù)量基本?致,但實際上絕?部分數(shù)據(jù)都只存儲在部分chunk上,導(dǎo)致這些熱點chunk所在的分?上的數(shù)據(jù)量遠遠?于其他分?上的數(shù)據(jù)量,執(zhí)行命令sh.status()
查看云數(shù)據(jù)庫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" }
云數(shù)據(jù)庫mongos負載均衡主要考慮的是各個shard的chunk數(shù)量保持相當(dāng),就認為數(shù)據(jù)是均衡的,所以就會出現(xiàn)以上的極端場景:雖然各個shard數(shù)量相當(dāng),但實際數(shù)據(jù)嚴重傾斜。因為?個chunk內(nèi)shardKey?乎完全相同但?觸發(fā)到64MB的chunk分裂閾值,這時就會分裂出?個空的chunk。久?久之,雖然chunk的數(shù)量變多了并且完成了chunk的遷移,但實際上遷移?的chunk都是空的chunk,造成了chunk數(shù)量均衡但實際數(shù)據(jù)不均衡的情況。對于這種情況,需要在架構(gòu)上重新設(shè)計,選擇合適的區(qū)分度較?的列作為sharding key。
spilt的介紹,詳情請參見sharding-data-partitioning和split-chunks-in-sharded-cluster。
部分db未做分片
云數(shù)據(jù)庫MongoDB分?集群實例允許部分db做分片,部分db不做分片。那么必然會帶來這樣的?個問題:不做分片的db的數(shù)據(jù)必然只能存在?個分?上,如果該db數(shù)據(jù)量很?,可能會造成該分?的數(shù)據(jù)量遠?于其他分?。
從?個源端mongos集群導(dǎo)?到?個新的mongos集群,但邏輯導(dǎo)?過程中忽略了實現(xiàn)在?標(biāo)端mongos集群做好分片設(shè)計的步驟。
針對上述問題,我們建議:
如果是因為?標(biāo)集群初始化導(dǎo)?,導(dǎo)?之前做好分?設(shè)計。
如果不做分片的庫很多且數(shù)據(jù)量基本相當(dāng),通過云數(shù)據(jù)庫MongoDB提供的命令
movePrimary
將指定數(shù)據(jù)庫遷移到指定分?。如果存在某個數(shù)據(jù)庫的數(shù)據(jù)量極?且未做分片,建議對其做分片設(shè)計或者將其拆分出來當(dāng)作單?的副本集對待。
如果出現(xiàn)這種情況,但磁盤空間足夠大,建議忽略該問題。
?規(guī)模的movechunk操作可能引起分?的磁盤占?不均
movechunk的本質(zhì)是向?標(biāo)端shard寫?數(shù)據(jù)后remove源端數(shù)據(jù)。默認情況下,remove操作不會釋放空間,因為對于wiredTiger引擎,每個表都有獨?的數(shù)據(jù)?件和索引?件,如果該?件不刪除,總的磁盤空間就不可能回縮。通常最容易引起該問題的操作為:之前的sharding集群中未做shard設(shè)計,運??段時間后才做了Sharding。
從原理上說movechunk引起的空間碎?和?規(guī)模刪除?樣,因此針對出現(xiàn)?量movechunk或者remove?檔的情況,可以針對該分?進?compact操作來回收碎?空間,正常情況下compact后數(shù)據(jù)會進?重組以回收?件的碎?空間。
movechunk的介紹,詳情請參見migrate-chunks-in-sharded-cluster和manage-sharded-cluster-balancer。