You need to enable JavaScript to run this app.
导航

通过 COMPACT 命令回收 MongoDB 分片集群磁盘碎片

最近更新时间2024.01.08 16:12:21

首次发布时间2023.09.18 15:16:10

本文介绍如何通过 compact 命令回收 MongoDB 分片集群实例的磁盘碎片,减少磁盘使用压力,提高利用率。

背景信息

文档数据库 MongoDB 版实例在删除数据时,不会直接回收被删除数据的磁盘空间(这些空间会被标记为空闲),后续新写入的数据不会占用新的磁盘空间,而是重用之前空闲的磁盘空间,那些未被使用的空闲存储空间则被称作磁盘碎片。随着删除的操作增多,碎片也会越来越多,磁盘碎片越多表明磁盘利用率越低。
Compact 命令可用于重写和整理 MongoDB 集合中所有的数据和索引,通过回收数据删除后所产生的磁盘碎片来提升磁盘利用率。关于 compact 命令的更多信息,请参见 compact

前提条件

  • 已分别获取 Shard 分片中主节点、从节点和隐藏节点的节点 ID。您可以在 MongoDB 控制台实例信息页签,在节点信息区域查看各角色节点对应的 ID 信息。具体方法,请参见查看实例信息
  • 已为目标 Shard 分片申请私网连接地址,并复制目标 Shard 分片私网连接地址。具体操作方法,请参见申请私网地址

    说明

    文档数据库 MongoDB 版分片集群实例只需回收 Shard 组件中对应节点的磁盘碎片。Mongos 和 ConfigServer 组件均不存储业务数据,并且增加和更新操作偏多,删除操作偏少,一般不需要回收磁盘碎片。

  • 通过 Shard 分片私网地址和分片中各节点 ID 生成对应节点的单节点连接私网地址。单节点连接地址格式如下。
    mongodb://<user>:<password>@<单节点连接地址前缀>.ivolces.com:3717 /?authSource=admin
    
    不同角色的单节点连接地址前缀不同,其中:

    说明

    本文以 s0 分片为例,其中主节点、从节点、隐藏节点 ID 后缀分别为 s00、s01、s02。

    • 主节点(Primary)对应的单节点连接地址前缀为 mongoshard****s00
    • 从节点(Secondary)对应的单节点连接地址前缀为 mongoshard****s01
    • 隐藏节点(Hidden)对应的单节点连接地址前缀为 mongoshard****s02

回收 Shard 磁盘碎片

说明

  • 建议在回收磁盘碎片前,先对数据库数据进行备份。数据备份的具体方法,请参见手动备份
  • 集合数据量、系统负载等因素会影响回收磁盘碎片的执行时间。
  • 您可以在回收磁盘碎片前,先通过 Mongo Shell 连接 MongoDB 分片集群实例并进入目标数据库,使用 db.stats() 命令查看数据库所占用的磁盘空间详情,便于在回收结束后确认磁盘碎片回收效果。
  • MongoDB 4.4 及之前的版本执行 compact 命令会导致集合所属的数据库被锁定,且会阻塞数据库的读写操作。建议您在业务低峰期,严格按照如下操作顺序进行磁盘碎片回收操作,减少对业务的影响。关于受阻塞命令的更多详情,请参见 Blocking

步骤一:回收 Hidden 节点上的磁盘碎片

  1. 在安装了 Mongo Shell 的本地服务器或 ECS 中,输入如下命令连接到分片集群实例的 Hidden 节点。

    mongo "<前提条件中生成且已设置了数据库账号名称和密码的 Hidden 节点连接地址>"
    

    示例如下。

    mongo "mongodb://root:Pwd_123@mongoshard****s02.mongodb.ivolces.com:3717/?authSource=admin"
    
  2. 执行 rs.isMaster() 命令确认当前连接的节点是否为 Hidden 节点。

    命令示例如下。

    rs-mongo-shard-****-s0:SECONDARY|test> rs.isMaster()
    
  3. 返回结果示例如下。

    说明

    如下示例中仅展示了部分字段,若 hidden 字段值为 true,即表明当前连接的是 Hidden 节点。

    {
            "hosts" : [
                    "mongoshard****s00.ivolces.com:3717",
                    "mongoshard****s01.ivolces.com:3717"
            ],
            "setName" : "rs-mongo-shard-****-s0",
            "setVersion" : 12444,
            "ismaster" : false,
            "secondary" : true,
            "primary" : "mongoshard****s00.ivolces.com:3717",
            "passive" : true,
            "hidden" : true,  
             ....... 
    }
    
  4. 执行如下 compact 命令回收磁盘碎片。

    db.runCommand({compact:"<collection_name>"})
    

    本文以 test_collect 为例,命令示例如下。

    db.runCommand({compact:"test_collect"})
    

    若返回结果中出现 "ok" : 1 ,即表示 compact 命令执行成功。

步骤二:回收 Secondary 节点上的磁盘碎片

  1. 在安装了 Mongo Shell 的本地服务器或 ECS 中,输入如下命令连接到分片集群实例的 Secondary 节点。

    mongo "<前提条件中生成且已设置了数据库账号名称和密码的 Secondary 节点连接地址>"
    

    示例如下。

    mongo "mongodb://root:Pwd_123@mongoshard****s01.mongodb.ivolces.com:3717/?authSource=admin"
    
  2. 执行 rs.isMaster() 命令确认当前连接的节点是否为 Secondary 节点。

    命令示例如下。

    rs-mongo-shard-****-s0:SECONDARY|test> rs.isMaster()
    
  3. 返回结果示例如下。

    说明

    返回结果中 secondary 字段值为 true,即表明当前连接的是 Secondary 节点。

    {
            "hosts" : [
                    "mongoshard****s00.ivolces.com:3717",
                    "mongoshard****s01.ivolces.com:3717"
            ],
            "setName" : "rs-mongo-shard-****-s0",
            "setVersion" : 12444,
            "ismaster" : false,
            "secondary" : true,
            "primary" : "mongoshard****s00.ivolces.com:3717",
            .......
    }
    
  4. 执行 compact 命令回收磁盘碎片。

    在 Secondary 节点中执行 compact 命令的方法和在 Hidden 节点上的一样。具体的命令详情和示例,请参见在 Hidden 节点上执行 COMPACT 命令

步骤三:手动切换主节点

手动将已完成磁盘碎片回收的从节点切换为主节点,详细操作步骤,请参见切换主节点

注意

  • 手动切换主节点过程(一般需要 30~60 秒)中,实例可能会出现 1~2 次连接闪断,请谨慎操作。建议在业务低峰期执行切换操作,并确保应用具备自动重连机制。
  • 手动切换主节点仅改变节点的角色,不会改变节点所在的可用区和节点 ID。

步骤四:回收新 Secondary 节点上的磁盘碎片

主节点切换成功后,参考回收 Secondary 节点上的磁盘碎片相关步骤,连接到切换后的 Secondary 节点并完成磁盘碎片回收。具体操作步骤,请参见回收 Secondary 节点上磁盘碎片

说明

所有节点上的磁盘碎片回收完成后,您可以再次通过 Mongo Shell 连接 MongoDB 分片集群实例并进入目标数据库,使用 db.stats() 命令查看数据库所占用的磁盘空间详情,与回收前的磁盘空间数据进行对比,确认磁盘碎片回收效果。