MongoDB
MongoDB 内存高问题
MongoDB 磁盘IO高问题
概述
阿里云数据库MongoDB的空间使用率是一个非常重要的监控指标,如果实例的存储空间完全打满,将会直接导致实例不可用。一般来说,当一个MongoDB实例的存储空间使用比例达到80-85%以上时,就应及时进行处理,要么降低数据库实际占用空间的大小,要么对存储空间进行扩容,以避免空间打满的风险。
然而,阿里云数据库MongoDB的空间使用情况分析并不简单,本文将由浅入深帮您查看,分析和优化云数据库MongoDB的空间使用。
查看空间使用
副本集模式
部署架构为副本集模式下,提供有多种查看空间使用的方法,您可以根据自身需求,由浅入深了解MongoDB的空间使用情况。
总体概览
在MongoDB控制台的“基本信息”页中会显示实例的总存储空间使用大小,但这里只有当前的空间的总使用率,没有具体的各类数据分别占用空间大小的信息,也没有空间使用的历史信息,如下图:
监控图分析
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
详细分析
如果需要深入分析副本集中库或表的空间详细占用,除了MongoDB自带的db.stats(),db.$collection_name.stats()以外,我们推荐使用阿里云MongoDB控制台的提供的"CloudDBA-空间分析",通过"CloudDBA-空间分析",您可以实现以下目的
• 查看库表空间概览,日均增长量,预测可用天数。
• 查看异常库表空间使用。
• 详细业务表的空间使用,包括索引和数据逻辑大小,压缩率分析,平均行长等更多内容。
更多的CloudDBA-空间分析内容参考:https://help.aliyun.com/document_detail/162422.html
更多mongodb官方提供的分析命令详解参考:
• 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/
分片集群
在分片集群的部署模式下,由于一个集群下可能存在多个Shard,没有整体空间使用率的概念。所以控制台不再提供"基本信息"中的空间使用率。
监控图分析
阿里云MongoDB的监控信息中详细提供了集群组建mongos路由节点,config server配置节点以及shard节点的空间使用率。不过通常来说,mongos和config server节点不会成为空间瓶颈,建议选择忽略,直接查看各个shard中各个角色的空间使用情况,如下图:
详细分析
分片集群的空间使用的详细查看方法与副本集模式略有不同,需要逐个登录各个shard通过命令查看,在每个分片上的空间使用情况详情就与副本集情况完全一样。
另外一方面,分片集群中的空间问题除了空间使用率以外,还存在非常大量的"各shard空间使用不均匀"问题,后者非常难以分析,目前CloudDBA暂不支持。本文后续章节会重点带您了解和深入分析“不同分片下空间使用不均衡”,“同一副本集下各个角色空间使用不均衡”。
空间问题的疑难杂症分析和解决方法
空间问题上涨概要分析和一般解决思路
当收到磁盘空间报警后,一般的分析和解决思路如下:

  1. 确认当前的空间使用值,确认当前空间使用中各个库表的详细占用情况。
  2. 确认引起空间增长的主要源头,比如是日志类增长,还是具体的某个业务表写入暴涨。
  3. 确认当前的增长是否符合预期,针对不符合预期的大量写入场景做应用分析。
  4. 确认当前的数据是否存在大量碎片,能否通过回收碎片的方式回收空间。
  5. 确认是否需要做磁盘空间扩容,或者部署定时历史数据删除或TTL Index。
  6. 历史数据大量删除完成,通过compact或者重做副本集的方式回收碎片空间。
    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.html
    compact无效
    如前文所述,在大量remove的场景下我们会需要使用compact来回收碎片空间。然而在极端场景下,compact操作虽然提示成功了,但实际上磁盘空间并没有回收,这应该算是一个BUG或者是MongoDB在compact设计上的缺陷,并不是只要存在碎片就一定能回收成功。compact的基本原理并不是立马开辟新的空间存放数据来替换原来的文件,而是将数据不断地往前面的空间空洞挪动,所以在某些场景下虽然存在空间空洞,但内部的compact算法并不能保证肯定可以复用这些空洞。针对这种compact失效的场景,如果纠结于空间使用,可以通过重建副本的方式解决。
    还有一种场景,在MongoDB3.4以前的版本,compact或许还存在一个BUG:在大量删除数据后,compact无法回收索引文件,只对数据文件生效。这个可以通过使用命令db.$table_name.stats().indexSizes或者直接查看索引物理文件大小确认。针对这种情况,建议将内核版本升级至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
    备库延迟和增量备份可能导致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 })
    不同分片之间的空间使用不均衡
    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/
    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。
    部分db未做sharding
    MongoDB分片集群允许部分db做sharding,部分db不做shading。那么必然会带来这样的一个问题:不做shading的db的数据必然只能存在一个分片上,如果该db数据量很大,可能会造成该分片的数据量远大于其他分片。
    除了上述情况,比较容易引起该问题的使用场景通常是因为从一个源端mongos集群导入到一个新的mongos集群,而逻辑导入过程中忽略了一步:实现在目标端mongos集群做好sharding设计,因为逻辑导入并不会自动做sharding设计,这一步需要事先做好。
    针对这种问题,我们建议:
    • 如果是因为目标集群初始化导入,导入之前做好分片设计。
    • 如果不做sharding的库很多且数据量基本相当,Mongos提供有movePriamy命令将指定db迁移到指定分片。
    • 如果存在某个db的数据量极大且未做sharding,建议对其做sharding设计或者将其拆分出来当作单一的副本集对待。
    • 即使出现这种情况,如果磁盘总量足够充裕,建议忽略。
    大规模的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/
    阿里云MongoDB产品在空间使用优化上的规划
    计算存储分离
    当前的阿里云MongoDB单个物理节点最大支持的存储空间是3T,如果单实例或副本集模式下的节点数据量超过3T就必须业务拆分或者升级至分片集群,而且规格扩容涉及到数据迁移会导致耗时较长。
    阿里云MongoDB在副本集部署模式下即将支持云盘以实现计算存储分离。在云盘存储下,单个节点的数据存储上限将达到数十T,以及云原生架构带来的分钟级扩容能力。
    ECS快照备份
    在高版本的阿里云MongoDB实例中,由于oplog多线程回放技术的越发成熟,基本上不会再有备库延迟问题,所以阿里云MongoDB内核层面不再对oplog做定制化改造,与官方的"固定集合"形态保持一致,备库延迟引起的oplog放大问题通过升级至最新版内核即可得到解决。
    另外,当前阿里云MongoDB正在研发采用ECS快照技术备份MongoDB实例,当故障发生时可绕过耗时的OSS物理备份下载,达到分钟级的恢复能力。并且使用ECS快照备份后,传统物理备份方式可能导致Hidden节点空间上涨的问题也会得到解决。
    Compact指令的内核改造优化
    MongoDB4.4的Compact指令并不会阻塞读写,阿里云MongoDB在内核层面将该patch移植至云数据库 MongoDB 3.4及以上版本,通过DAS控制台点击的方式实现空间碎片整理的产品化。

MongoDB 空间使用相关推荐

  1. mongodb空间查询之查询单位

    1.建立空间索引 db.collection.ensureIndex({'geom.coordinates':'2d'}) 2.空间查询 这里遇到的问题是查询的时候会涉及到范围,那么这个范围的单位是什 ...

  2. Java监控MongoDB空间使用量、连接数

    最近在做一个Java开发的监控系统,里面有一个模块是监控MongoDB的.看到网络上比较少这块资料,特记录如下: 1.下载MongoDB的Java驱动包 mongo-java-driver-3.1.1 ...

  3. mongodb空间查询java,java查看mongodb集合表空间大小

    话不多说先粘代码: MongoDatabase db = mongoTemplate.getDb(); Document collStats = db.runCommand(new Document( ...

  4. mongodb java连接数_Java监控MongoDB空间使用量、连接数

    获取到的数据如下: { "serverUsed": "172.1.1.3:15080", "db": "monitor" ...

  5. MongoDB负载信息一目了然 阿里云HDM重磅发布MongoDB监控和诊断功

    混合云数据库管理(HDM)的统一监控.告警.诊断功能新增了对MongoDB的支持. 通过直观的方式将MongoDB多个维度的负载信息统一整合,不仅可以清晰的查看实时负载信息,也可以方便的确认历史负载情 ...

  6. mongoDB之ObjectId

    mongoDB之ObjectId 一.ObjectId介绍     我们在使用mongodb插入数据时,每个document中必须有一个_id字段,且可以是任意类型,但如果没有单独设置_id字段,mo ...

  7. 解决MongoDB 日志文件过大,清理后还占用很大磁盘空间的问题

    解决MongoDB 日志文件过大,清理后还占用很大磁盘空间的问题 参考文章: (1)解决MongoDB 日志文件过大,清理后还占用很大磁盘空间的问题 (2)https://www.cnblogs.co ...

  8. mongoDB 删除集合后,空间不释放的解决方法

    mongoDB 删除集合后,空间不释放的解决方法 参考文章: (1)mongoDB 删除集合后,空间不释放的解决方法 (2)https://www.cnblogs.com/ddbear/p/71116 ...

  9. mongodb 查看数据库和空间大小

    mongodb 查看数据库和空间大小 单位是M db.stats(1048576); 单位是G db.stats(1073741824); posted on 2019-02-22 17:36 luo ...

最新文章

  1. Gibbs sampling
  2. c#滚动条创建实例,多线程
  3. LeetCode139:Word Break
  4. 关于微信“被返回页”在被返回时自动刷新
  5. 手机发电脑邮箱未开启服务器,手机邮箱无法发送和接收邮件时发生了什么
  6. ImageMagick---import(截图)
  7. JVM指令集(指令码、助记符、功能描述)(转)
  8. hbase使用restful接口进行数据操作
  9. DiscuzNT改造系列之删除帖子后论坛版块列表同步更新
  10. 简单了解下什么是中台?
  11. openresty ngx_lua常用指令
  12. oracle AWR 报告 中文版
  13. 金立 M6 (GN8003) 解锁 BootLoader 进入第三方 recovery 刷机 ROOT
  14. OPPOEncoFree2配对
  15. 计算机考研817,2017年南京工业大学计算机科学与技术学院817信号系统与数字电路考研题库...
  16. C++ Primer Plus(第六版)第4章 编程练习答案详解
  17. 计算机技术 食堂管理,食堂管理系统需求规格说明.doc
  18. 基于机器学习k-近邻算法完成一个电影是爱情片还是动作片的判断
  19. AVG 2017 PC TuneUp
  20. 中国风水墨风企业通用 (2)PPT模板

热门文章

  1. 2018软工实践—Alpha冲刺(9)
  2. Android O 前期预研之三:Android Vehicle HAL
  3. 排列组合问题的C++代码
  4. go --- 正则匹配根域名
  5. ipad忘记锁屏密码用计算机解决,4种无需密码即可解锁iPad的方法
  6. 犀思云—混合云基础设施解决方案市场研究分析
  7. 对sqrt未定义的引用 matlab,未定义对sqrt的引用(或其他数学函数)
  8. 华为近场通讯nfc在哪里打开_NFC近场通讯简单介绍
  9. 设计模式学习(十四) 责任链模式 COR
  10. Win11连接共享打印机错误0x00000bc4