Skip to content

MongoDB 空间监控与告警

空间使用分析

数据库空间使用

  1. 查看数据库大小
    javascript
    // 查看所有数据库大小
    db.adminCommand({ listDatabases: 1, nameOnly: false, filter: {} })
    
    // 查看特定数据库大小
    use mydatabase

db.stats()


2. **数据库大小组成**
- `dataSize`:数据大小
- `indexSize`:索引大小
- `storageSize`:存储大小(包括预分配空间)
- `fsUsedSize`:文件系统实际使用大小

3. **查看集合大小**
```javascript
// 查看所有集合大小
db.getCollectionNames().forEach(function(col) {
  print(col + ": " + db[col].stats().size / 1024 / 1024 + " MB");
});

// 查看特定集合大小
db.mycollection.stats()

存储引擎空间使用

  1. WiredTiger 存储引擎

    javascript
    // 查看 WiredTiger 缓存使用情况
    db.serverStatus().wiredTiger.cache
    
    // 查看 WiredTiger 存储统计
    db.serverStatus().wiredTiger.session
  2. WiredTiger 数据压缩

    javascript
    // 查看集合压缩统计
    db.mycollection.stats().wiredTiger.compression
  3. MMAPv1 存储引擎(已弃用)

    javascript
    // 查看 MMAPv1 命名空间信息
    db.adminCommand({ mmapv1Stats: 1 })

磁盘空间监控

  1. 查看磁盘分区使用情况

    bash
    # Linux
    df -h
    
    # Windows
    wmic logicaldisk get size,freespace,caption
  2. MongoDB 数据目录使用情况

    bash
    # 查看数据目录大小
    du -sh /data/mongodb
    
    # 查看数据文件大小
    ls -lh /data/mongodb/*.wt
  3. 预分配空间管理

    javascript
    // 查看预分配空间设置
    db.adminCommand({ getParameter: 1, storage.wiredTiger.engineConfig.directoryForIndexes: 1 })
    
    // 调整预分配策略
    // 在配置文件中设置
    // storage:
    //   wiredTiger:
    //     collectionConfig:
    //       blockCompressor: zlib

监控工具与命令

MongoDB 内置监控命令

  1. db.stats()

    javascript
    // 数据库级统计
    db.stats()
    
    // 详细统计
    db.stats(1024) // 以 KB 为单位
    db.stats(1048576) // 以 MB 为单位
  2. db.collection.stats()

    javascript
    // 集合级统计
    db.mycollection.stats()
    
    // 包含索引统计
    db.mycollection.stats({ indexDetails: true })
  3. db.serverStatus()

    javascript
    // 服务器级统计
    db.serverStatus().storageEngine
    db.serverStatus().metrics.storage
  4. db.adminCommand()

    javascript
    // 查看所有数据库大小
    db.adminCommand({ listDatabases: 1 })
    
    // 查看操作统计
    db.adminCommand({ serverStatus: 1, recordStats: 1 })

第三方监控工具

  1. MongoDB Atlas

    • 内置存储监控仪表盘
    • 自动空间告警
    • 存储使用趋势分析
  2. MongoDB Ops Manager

    • 存储监控和告警
    • 空间使用预测
    • 自动清理建议
  3. Prometheus + Grafana

    • 自定义存储监控仪表盘
    • 灵活的告警规则
    • 长期存储使用趋势
  4. Datadog

    • MongoDB 集成
    • 存储使用监控
    • 智能告警
  5. Nagios/Zabbix

    • 传统监控工具
    • 自定义 MongoDB 监控脚本
    • 成熟的告警机制

自定义监控脚本

  1. Python 监控脚本

    python
    #!/usr/bin/env python3
    from pymongo import MongoClient
    import subprocess
    
    # 连接 MongoDB
    client = MongoClient('mongodb://localhost:27017')
    
    # 查看数据库大小
    databases = client.admin.command('listDatabases')
    for db in databases['databases']:
        print(f"Database: {db['name']}, Size: {db['sizeOnDisk'] / 1024 / 1024:.2f} MB")
    
    # 查看磁盘空间
    result = subprocess.run(['df', '-h'], capture_output=True, text=True)
    print("\nDisk Space:")
    print(result.stdout)
    
    client.close()
  2. Shell 监控脚本

    bash
    #!/bin/bash
    
    # 查看 MongoDB 数据库大小
    echo "MongoDB Database Sizes:"

mongo --eval "db.adminCommand({ listDatabases: 1 })" | grep -E "name|sizeOnDisk"

查看数据目录大小

echo "\nData Directory Size:"
du -sh /data/mongodb

查看磁盘空间

echo "\nDisk Space Usage:"
df -h


## 空间告警设置

### MongoDB Atlas 告警

1. **配置空间告警**
- 登录 Atlas 控制台
- 导航到 "Alerts" 页面
- 点击 "Add Alert" 按钮
- 选择 "Storage" 作为告警类别
- 设置告警条件,如 "Disk Usage % > 80%"
- 配置通知方式(邮件、Slack、PagerDuty 等)

2. **常用告警阈值**
- 磁盘使用率 > 80%
- 数据库大小增长速率异常
- 单集合大小超过阈值

### MongoDB Ops Manager 告警

1. **配置空间告警**
- 登录 Ops Manager 控制台
- 导航到 "Alert Settings" 页面
- 点击 "Add Alert Configuration" 按钮
- 选择 "Host" 作为告警目标
- 设置 "Disk Partition Usage %" 告警条件
- 配置通知渠道

2. **告警通知策略**
- 分级告警:警告(80%)、严重(90%)、紧急(95%)
- 告警升级机制
- 告警抑制规则

### Prometheus + Grafana 告警

1. **Prometheus 告警规则**
```yaml
groups:
- name: mongodb_space_alerts
  rules:
  - alert: MongoDBHighDiskUsage
    expr: (node_filesystem_size_bytes{mountpoint="/data"} - node_filesystem_free_bytes{mountpoint="/data"}) / node_filesystem_size_bytes{mountpoint="/data"} * 100 > 80
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: "High disk usage on {{ $labels.instance }}"
      description: "Disk usage is at {{ $value | printf \"%.2f\" }}%"
  
  - alert: MongoDBVeryHighDiskUsage
    expr: (node_filesystem_size_bytes{mountpoint="/data"} - node_filesystem_free_bytes{mountpoint="/data"}) / node_filesystem_size_bytes{mountpoint="/data"} * 100 > 90
    for: 5m
    labels:
      severity: critical
    annotations:
      summary: "Very high disk usage on {{ $labels.instance }}"
      description: "Disk usage is at {{ $value | printf \"%.2f\" }}%"
  1. Grafana 告警配置
    • 在 Grafana 中创建告警规则
    • 设置查询和阈值
    • 配置通知渠道
    • 测试告警

自定义告警脚本

  1. Python 告警脚本

    python
    #!/usr/bin/env python3
    from pymongo import MongoClient
    import smtplib
    from email.mime.text import MIMEText
    
    # 连接 MongoDB
    client = MongoClient('mongodb://localhost:27017')
    
    # 检查数据库大小
    db = client.mydatabase
    stats = db.stats()
    db_size_mb = stats['sizeOnDisk'] / 1024 / 1024
    
    # 告警阈值(MB)
    ALERT_THRESHOLD = 10000  # 10GB
    
    if db_size_mb > ALERT_THRESHOLD:
        # 发送邮件告警
        msg = MIMEText(f"MongoDB database size exceeded threshold: {db_size_mb:.2f} MB")
        msg['Subject'] = 'MongoDB Space Alert'
        msg['From'] = 'alert@example.com'
        msg['To'] = 'admin@example.com'
        
        with smtplib.SMTP('smtp.example.com') as server:
            server.login('username', 'password')
            server.send_message(msg)
    
    client.close()
  2. Shell 告警脚本

    bash
    #!/bin/bash
    
    # 检查 MongoDB 数据目录大小
    DATA_DIR="/data/mongodb"
    MAX_SIZE_GB=50
    
    CURRENT_SIZE_GB=$(du -s $DATA_DIR | awk '{print $1 / 1024 / 1024}')
    
    if (( $(echo "$CURRENT_SIZE_GB > $MAX_SIZE_GB" | bc -l) )); then
        # 发送告警
        echo "MongoDB data directory size exceeded $MAX_SIZE_GB GB: $CURRENT_SIZE_GB GB" | mail -s "MongoDB Space Alert" admin@example.com
    fi

空间管理与优化

数据压缩

  1. WiredTiger 压缩配置

    javascript
    // 创建使用压缩的集合
    db.createCollection("mycollection", {
      storageEngine: {
        wiredTiger: {
          configString: "block_compressor=zstd"
        }
      }
    })
    
    // 压缩现有集合
    db.runCommand({
      compact: "mycollection"
    })
  2. 压缩算法选择

    • zlib:平衡压缩率和性能
    • snappy:高性能,适合写入密集型应用
    • zstd:高压缩率,适合读取密集型应用
  3. 索引压缩

    javascript
    // 创建使用压缩的索引
    db.mycollection.createIndex({
      field: 1
    }, {
      storageEngine: {
        wiredTiger: {
          configString: "prefix_compression=true"
        }
      }
    })

数据归档

  1. TTL 索引

    javascript
    // 创建 TTL 索引,数据自动过期
    db.mycollection.createIndex(
      { "createdAt": 1 },
      { expireAfterSeconds: 86400 } // 24小时
    )
  2. 手动归档

    javascript
    // 复制数据到归档集合
    db.mycollection.aggregate([
      { $match: { createdAt: { $lt: new Date(Date.now() - 365 * 24 * 60 * 60 * 1000) } } },
      { $out: "mycollection_archive_2023" }
    ])
    
    // 删除旧数据
    db.mycollection.deleteMany({
      createdAt: { $lt: new Date(Date.now() - 365 * 24 * 60 * 60 * 1000) }
    })
  3. 分区集合

    javascript
    // 创建分区集合
    db.createCollection("mycollection", {
      shardKey: { "createdAt": 1 },
      collation: { locale: "en_US" }
    })

碎片整理

  1. WiredTiger 碎片整理

    javascript
    // 整理集合碎片
    db.runCommand({
      compact: "mycollection"
    })
    
    // 整理数据库碎片
    db.runCommand({
      compact: 1
    })
  2. 注意事项

    • compact 命令会锁定集合
    • 建议在低峰期执行
    • 可能需要额外的磁盘空间
    • 对于分片集群,需要在每个分片上执行

扩展存储

  1. 垂直扩展

    • 增加服务器磁盘空间
    • 迁移到更大的存储设备
  2. 水平扩展

    • 分片集群扩容
    • 添加新分片
    • 数据重平衡
  3. 云存储扩展

    • AWS EBS 卷扩展
    • Azure 磁盘扩展
    • Google Cloud 持久磁盘扩展

最佳实践

监控最佳实践

  1. 定期监控

    • 设置合理的监控频率
    • 保留足够的监控历史数据
    • 建立空间使用基线
  2. 多维度监控

    • 数据库级监控
    • 集合级监控
    • 磁盘级监控
    • 存储引擎级监控
  3. 告警最佳实践

    • 设置多级告警阈值
    • 配置合适的告警通知方式
    • 建立告警响应流程
    • 定期测试告警

空间管理最佳实践

  1. 合理规划存储

    • 预估数据增长
    • 预留足够的磁盘空间
    • 考虑压缩和归档策略
  2. 定期清理

    • 删除不再需要的数据
    • 清理临时集合
    • 定期整理碎片
  3. 优化数据模型

    • 避免过度嵌套
    • 合理使用索引
    • 考虑数据分片策略
  4. 存储引擎优化

    • 选择合适的压缩算法
    • 调整缓存大小
    • 优化预分配策略

常见问题(FAQ)

Q1: 如何查看 MongoDB 数据文件大小?

A1: 使用以下命令:

bash
ls -lh /data/mongodb/*.wt

javascript
db.stats().storageSize

Q2: MongoDB 磁盘空间不足会发生什么?

A2: 磁盘空间不足可能导致:

  • 写入操作失败
  • 数据库锁定
  • 服务崩溃
  • 数据损坏风险

Q3: 如何清理 MongoDB 磁盘空间?

A3: 清理磁盘空间的方法:

  • 删除不再需要的数据
  • 使用 TTL 索引自动过期数据
  • 归档旧数据
  • 执行 compact 命令整理碎片
  • 调整存储引擎配置

Q4: 如何预测 MongoDB 空间增长?

A4: 预测空间增长的方法:

  • 分析历史空间使用趋势
  • 考虑业务增长
  • 使用监控工具的预测功能
  • 定期进行容量规划

Q5: WiredTiger 压缩能节省多少空间?

A5: 压缩效果取决于数据类型:

  • 文本数据:可节省 50-80%
  • 二进制数据:可节省 10-30%
  • 已压缩数据:几乎不节省

Q6: 如何监控 MongoDB 分片集群的空间使用?

A6: 监控分片集群空间使用的方法:

javascript
// 查看分片状态
sh.status()

// 查看集合分片分布
db.collection.getShardDistribution()

// 查看每个分片的空间使用
use admin
db.runCommand({ listDatabases: 1, shard: "shard1" })

Q7: 什么是 MongoDB 预分配空间?

A7: MongoDB 会预分配数据文件以避免频繁的文件系统操作,预分配的文件大小会逐渐增长,直到达到 2GB。可以通过配置调整预分配策略。

Q8: 如何处理 MongoDB 数据文件碎片?

A8: 处理数据文件碎片的方法:

javascript
// 整理集合碎片
db.runCommand({ compact: "mycollection" })

Q9: 如何设置 MongoDB 空间告警?

A9: 设置空间告警的方法:

  • 使用 MongoDB Atlas 或 Ops Manager 的内置告警功能
  • 使用 Prometheus + Grafana 自定义告警
  • 编写自定义告警脚本

Q10: MongoDB 空间使用与性能有什么关系?

A10: 空间使用与性能的关系:

  • 磁盘空间不足会导致性能下降
  • 过多的碎片会影响 I/O 性能
  • 合理的压缩可以提高性能
  • 适当的索引可以提高查询性能,但会增加存储空间