MongoDB 空间使用问题

本文涉及的产品
云原生多模数据库 Lindorm,多引擎 多规格 0-4节点
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
云数据库 MongoDB,通用型 2核4GB
简介: MongoDB 空间使用问题

概述

阿里云数据库MongoDB的空间使用率是一个非常重要的监控指标,如果实例的存储空间完全打满,将会直接导致实例不可用。一般来说,当一个MongoDB实例的存储空间使用比例达到80-85%以上时,就应及时进行处理,要么降低数据库实际占用空间的大小,要么对存储空间进行扩容,以避免空间打满的风险。

然而,阿里云数据库MongoDB的空间使用情况分析并不简单,本文将由浅入深帮您查看,分析和优化云数据库MongoDB的空间使用。

1 查看空间使用

1.1 副本集模式

部署架构为副本集模式下,提供有多种查看空间使用的方法,您可以根据自身需求,由浅入深了解MongoDB的空间使用情况。

1.2总体概览

MongoDB控制台的基本信息页中会显示实例的总存储空间使用大小,但这里只有当前的空间的总使用率,没有具体的各类数据分别占用空间大小的信息,也没有空间使用的历史信息,如下图:

                             

1.3 监控图分析

MongoDB副本集由多种角色组成,一个角色可能对应一个或多个物理节点。阿里云MongoDB对用户暴露PrimarySecondary节点,另外还提供有只读实例的角色。可以通过点击"监控信息",选择对应的角色查看MongoDB空间相关的监控情况,如下图:

其中一个MongoDB物理节点的空间使用由两大块组成,分别为data_sizelog_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/

l  https://docs.mongodb.com/manual/reference/method/db.collection.stats/

l  https://docs.mongodb.com/manual/reference/method/db.collection.storageSize/

l  https://docs.mongodb.com/manual/reference/method/db.collection.totalIndexSize/

l  https://docs.mongodb.com/manual/reference/method/db.collection.totalSize/

2 分片集群

在分片集群的部署模式下,由于一个集群下可能存在多个Shard,没有整体空间使用率的概念。所以控制台不再提供"基本信息"中的空间使用率。

2.1 监控图分析

阿里云MongoDB的监控信息中详细提供了集群组建mongos路由节点,config server配置节点以及shard节点的空间使用率。不过通常来说,mongosconfig 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的命令的使用方法和限制参考:

l  https://docs.mongodb.com/manual/reference/command/compact/

l  https://mongoing.com/archives/26907

l  https://help.aliyun.com/document_detail/96530.html

3.3 compact无效

如前文所述,在大量remove的场景下我们会需要使用compact来回收碎片空间。然而在极端场景下,compact操作虽然提示成功了,但实际上磁盘空间并没有回收,这应该算是一个BUG或者是MongoDBcompact设计上的缺陷,并不是只要存在碎片就一定能回收成功。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-4083

3.5备库延迟和增量备份可能导致Secondary日志空间持续增长

默认的官方MongoDBoplog是一个固定集合,大小基本是固定的,主备之间的物理文件大小不会有太大差异。阿里云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类型介绍参考:

l  https://docs.mongodb.com/manual/core/sharding-shard-key/

l  https://docs.mongodb.com/manual/core/hashed-sharding/

l  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负载均衡主要考虑的是各个shardchunk数量保持相当,就认为数据是均衡的,所以就会出现以上的极端场景:虽然各个shard数量相当,但实际数据严重倾斜。因为一个chunkshardKey几乎完全相同但又触发到64Mchunk分裂阈值,这时就会分裂出一个空的chunk。久而久之,虽然chunk的数量变多了并且完成了chunk的迁移,但实际上迁移走的chunk都是空的chunk,造成了chunk数量均衡但实际数据不均衡的情况。(这应该是Balancer在迁移chunk时基于代价的考虑,认为空chunk迁移代价更低,所以优先选了空的chunk迁移)

更多split的介绍参考:

l  https://docs.mongodb.com/manual/core/sharding-data-partitioning/

l  https://docs.mongodb.com/manual/tutorial/split-chunks-in-sharded-cluster/

针对这种情况,只能在架构上重新设计,选择合适的区分度较高的列作为sharding key

4.3 部分db未做sharding

MongoDB分片集群允许部分dbsharding,部分db不做shading。那么必然会带来这样的一个问题:不做shadingdb的数据必然只能存在一个分片上,如果该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的介绍参考:

l  https://docs.mongodb.com/manual/tutorial/migrate-chunks-in-sharded-cluster/

l  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下载完整版,助力云运维能力更上一层楼!



相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。   相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
相关文章
|
11月前
|
NoSQL Shell MongoDB
一日一技:单机单节点 MongoDB 为什么删除数据后不释放空间?
一日一技:单机单节点 MongoDB 为什么删除数据后不释放空间?
524 0
|
11月前
|
NoSQL MongoDB 数据库
一日一技:如何找到 MongoDB 占用空间最大的集合?
一日一技:如何找到 MongoDB 占用空间最大的集合?
252 0
|
SQL 存储 监控
【巡检问题分析与最佳实践】MongoDB 空间使用问题
阿里云数据库MongoDB的空间使用率是一个非常重要的监控指标,如果实例的存储空间完全打满,将会直接导致实例不可用。一般来说,当一个MongoDB实例的存储空间使用比例达到80-85%以上时,就应及时进行处理,要么降低数据库实际占用空间的大小,要么对存储空间进行扩容,以避免空间打满的风险。 然而,阿里云数据库MongoDB的空间使用情况分析并不简单,本文将由浅入深帮您查看,分析和优化云数据库MongoDB的空间使用。
【巡检问题分析与最佳实践】MongoDB 空间使用问题
|
3月前
|
JSON NoSQL 小程序
Mongodb数据库的导出和导入总结
Mongodb数据库的导出和导入总结
198 0
|
3天前
|
NoSQL MongoDB 数据库
MongoDB数据恢复—MongoDB数据库文件被破坏的数据恢复案例
服务器数据恢复环境: 一台Windows Server操作系统服务器,服务器上部署MongoDB数据库。 MongoDB数据库故障&检测: 工作人员在未关闭MongoDB数据库服务的情况下,将数据库文件拷贝到其他分区。拷贝完成后将原MongoDB数据库所在分区进行了格式化操作,然后将数据库文件拷回原分区,重新启动MongoDB服务,服务无法启动。
|
7天前
|
NoSQL MongoDB Redis
Python与NoSQL数据库(MongoDB、Redis等)面试问答
【4月更文挑战第16天】本文探讨了Python与NoSQL数据库(如MongoDB、Redis)在面试中的常见问题,包括连接与操作数据库、错误处理、高级特性和缓存策略。重点介绍了使用`pymongo`和`redis`库进行CRUD操作、异常捕获以及数据一致性管理。通过理解这些问题、易错点及避免策略,并结合代码示例,开发者能在面试中展现其技术实力和实践经验。
129 8
Python与NoSQL数据库(MongoDB、Redis等)面试问答
|
1月前
|
NoSQL 网络协议 MongoDB
Windows公网远程连接MongoDB数据库【无公网IP】
Windows公网远程连接MongoDB数据库【无公网IP】
|
1月前
|
存储 NoSQL 关系型数据库
一篇文章带你搞懂非关系型数据库MongoDB
一篇文章带你搞懂非关系型数据库MongoDB
58 0
|
1月前
|
人工智能 NoSQL MongoDB

相关产品

  • 云数据库 MongoDB 版