ApsaraDB for MongoDB執行個體的空間使⽤率是⼀個⾮常重要的監控指標。如果MongoDB執行個體的空間被完全使用,將會導致執行個體不可⽤。本文介紹查看MongoDB執行個體空間使用方式的方法,以及各種空間使用方式的原因和最佳化策略。
背景資訊
執行個體空間使用率達到80%~85%以上時,可通過降低資料庫實際佔用空間或擴容儲存空間的方法避免空間佔滿的風險。
查看空間使用方式
複本集架構
當ApsaraDB for MongoDB執行個體為複本集架構時,您可以登入MongoDB管理主控台通過以下方法查看空間使用方式:
總體概覽
在基本資料頁面的規格資訊地區,查看當前執行個體的磁碟空間和使用率。
監控圖分析
在左側導覽列中單擊監控資訊,選擇目標節點,查看目標節點的磁碟空間使用量(Bytes)和磁碟空間使用率(%)。
ApsaraDB for MongoDB複本集執行個體提供一個可供讀寫訪問的Primary節點(主節點)、一個或多個提供高可用的Secondary節點(從節點)、一個隱藏的Hidden節點(隱藏節點)和一個或多個可選的ReadOnly節點(唯讀節點)。MongoDB節點的空間使用量由data_size和log_size組成,即ins_size=data_size+log_size。其中:
data_size:資料磁碟使⽤空間(不包括local庫),主要包括collection開頭的資料物理⽂件,索引開頭的索引物理⽂件和部分中繼資料物理⽂件,例如WiredTiger.wt。
log_size:local庫的物理⼤⼩、mongodb運⾏⽇志⼤⼩和部分審計⽇志⼤⼩。
詳細分析
您可以通過以下兩種方法詳細分析空間使用問題:
通過MongoDB自身提供的命令
db.stats()
和db.$collection_name.stats()
分析。在
頁面分析。您可以在
頁面查看以下配置資訊:資料庫和表使用空間情況概覽、⽇均增⻓量和預測可⽤天數。
異常資料庫和表使用空間情況。
詳細業務表使用空間情況,包括索引檔案大小、資料檔案大小,壓縮率分析,平均⾏⻓等。
分⽚叢集架構
當ApsaraDB for MongoDB執行個體為分區叢集架構時,您可以登入MongoDB管理主控台通過以下方法查看空間使用方式:
監控圖分析
在監控資訊頁面,選擇目標節點,查看目標節點的磁碟空間使用量(Bytes)和磁碟空間使用率(%)。
詳細分析
通過ApsaraDB for MongoDB自身提供的命令
db.stats()
和db.$collection_name.stats()
依次分析各個節點的空間使用方式。
執行compact指令導致資料量過大
compact期間對執行個體的影響
由於compact執⾏的時間與集合的資料量相關,如果資料量過大,則會使compact的執行時間很長,所以為避免影響業務的讀寫,建議在業務低峰期執⾏compact。
compact⽅法
首先在備庫上執行命令db.runCommand({compact:"collectionName"})
,然後進行主備切換,以減少compact期間對業務的影響。其中collectionName
為集合名稱,請根據實際情況替換。
MongoDB 4.2及以前的官方版本,compact命令會阻塞業務正常讀寫,建議您僅在沒有業務流量的Secondary節點上執行該操作。
MongoDB 4.4及以後的官方版本,compact命令將不再阻塞業務讀寫,但是在Primary節點執行compact命令,有可能會對執行個體效能產生影響,建議您在Secondary或Hidden節點上執行。如果您必須要在Primary節點執行compact命令,建議您在業務低峰期進行操作。compact命令的使用方法和限制請參見:compact、MongoDB命令詳解和回收磁碟片段以提升磁碟利用率。
MongoDB 4.4.9以前的官方版本,正在執行compact命令的節點會進入RECOVERING狀態,如果期間過長,該節點會被執行個體探活組件認定為節點不健康從而觸發相應的重搭操作;MongoDB 4.4.9及以後的官方版本,正在執行compact命令的節點則會維持在SECONDARY狀態。詳細資料,請參見MongoDB官方文檔。
如果您的MongoDB執行個體大版本為4.4但不確定小版本是否大於4.4.9,請提交工單聯絡阿里雲支援人員進行確認。
compact⽆效
compact的基本原理並不是⽴⻢開闢新的空間存放資料來替換原來的⽂件,⽽是將資料不斷地往前⾯的空間空洞挪動,所以在某些情境下雖然存在空間空洞,但內部的compact演算法並不能保證肯定可以複⽤這些空洞,我們稱之為compact無效。compact無效的情境和解決方案如下:
在完成compact後,雖然提示操作成功,但實際上磁碟空間並沒有回收,對於該情境,建議您通過重建副本的方式解決。
MongoDB 3.4以前的版本,在刪除大量資料後,compact⽆法回收索引檔案,只對資料⽂件⽣效,對於該情境,建議您將核心版本升級⾄3.4以上。您可以通過如下方法確認該情境:
執行命令
db.$table_name.stats().indexSizes
。查看索引物理檔案大小。
日誌過大導致空間上漲
Journal Log過⼤導致主備空間差距巨⼤
ApsaraDB for MongoDB 4.0以前的版本,如果宿主機的open files達到設定上限,則會使ApsaraDB for MongoDB內部的log server清理線程中斷,進而使Journal Log過大導致空間無限上漲,當通過ApsaraDB for MongoDB的作業記錄查看到類似以下內容時,您可以將核心版本升級到ApsaraDB for MongoDB 4.0以上,或者通過重啟雲資料庫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.
備庫延遲和增量備份可能導致從節點⽇志空間持續增⻓
ApsaraDB for MongoDB在出現主備延遲的情況下,Oplog可以使用的大小不再受限於設定檔定義的固定集合大小,理論上使得可以達到使用者申請磁碟容量的20%,但當備庫延遲恢複後,Oplog之前占⽤的物理空間並不會回縮。
ApsaraDB for MongoDB使⽤物理備份的⽅式在隱藏節點備份ApsaraDB for MongoDB執行個體期間會有⼤量的checkpoint,進而導致占⽤了更多的資料和⽇志空間。
對於以上兩種情境,通過對Oplog單獨做compact操作解決,具體如下:
進行compact期間會阻塞所有的寫操作。
db.grantRolesToUser("root", [{db: "local", role: "dbAdmin"}])
use local
db.runCommand({ compact: "oplog.rs", force: true })
選擇和使用分區不合理導致資料分布不均衡
sharding key類型選擇不合理
在⼀個分⽚叢集中,⽚鍵類型的選擇⾄關重要,⼀般會使⽤hash分⽚或者ranged分⽚兩種類型。通常情況下,在磁碟均衡度⽅⾯,hash分⽚的策略會⽐ranged好很多,因為根據不同的key值,ApsaraDB for MongoDB通過內部的雜湊函數可以使得資料均勻地分布在不同地分⽚上,⽽range分⽚⼀般是根據key的⼤⼩範圍進⾏資料分布,所以往往會造成這樣的⼀個現象:新插⼊的資料在⼀個熱點的chunk上,不但會引起該chunk所在的shard磁碟I/O過⾼,也會帶來短期資料不均勻的情境。
Sharding Key類型的介紹,詳情請參見sharding-shard-key、hashed-sharding和ranged-sharding。
sharding key欄位選擇不合理
各個分⽚上的chunk數量基本⼀致,但實際上絕⼤部分資料都只儲存在部分chunk上,導致這些熱點chunk所在的分⽚上的資料量遠遠⼤於其他分⽚上的資料量,執行命令sh.status()
查看ApsaraDB for 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⼏乎完全相同但⼜觸發到64MB的chunk分裂閾值,這時就會分裂出⼀個空的chunk。久⽽久之,雖然chunk的數量變多了並且完成了chunk的遷移,但實際上遷移⾛的chunk都是空的chunk,造成了chunk數量均衡但實際資料不均衡的情況。對於這種情況,需要在架構上重新設計,選擇合適的區分度較⾼的列作為sharding key。
spilt的介紹,詳情請參見sharding-data-partitioning和split-chunks-in-sharded-cluster。
部分db未做分區
ApsaraDB for MongoDB分⽚叢集執行個體允許部分db做分區,部分db不做分區。那麼必然會帶來這樣的⼀個問題:不做分區的db的資料必然只能存在⼀個分⽚上,如果該db資料量很⼤,可能會造成該分⽚的資料量遠⼤於其他分⽚。
從⼀個源端mongos叢集導⼊到⼀個新的mongos叢集,但邏輯導⼊過程中忽略了實現在⽬標端mongos叢集做好分區設計的步驟。
針對上述問題,我們建議:
如果是因為⽬標叢集初始化導⼊,導⼊之前做好分⽚設計。
如果不做分區的庫很多且資料量基本相當,通過ApsaraDB for MongoDB提供的命令
movePrimary
將指定資料庫遷移到指定分⽚。如果存在某個資料庫的資料量極⼤且未做分區,建議對其做分區設計或者將其拆分出來當作單⼀的複本集對待。
如果出現這種情況,但磁碟空間足夠大,建議忽略該問題。
⼤規模的movechunk操作可能引起分⽚的磁碟占⽤不均
movechunk的本質是向⽬標端shard寫⼊資料後remove源端資料。預設情況下,remove操作不會釋放空間,因為對於wiredTiger引擎,每個表都有獨⽴的資料⽂件和索引⽂件,如果該⽂件不刪除,總的磁碟空間就不可能回縮。通常最容易引起該問題的操作為:之前的sharding叢集中未做shard設計,運⾏⼀段時間後才做了Sharding。
從原理上說movechunk引起的空間碎⽚和⼤規模刪除⼀樣,因此針對出現⼤量movechunk或者remove⽂檔的情況,可以針對該分⽚進⾏compact操作來回收碎⽚空間,正常情況下compact後資料會進⾏重組以回收⽂件的碎⽚空間。
movechunk的介紹,詳情請參見migrate-chunks-in-sharded-cluster和manage-sharded-cluster-balancer。