4. 集群配置管理
当 MongoDB 集群从“能跑起来”进入“长期稳定运行”阶段,配置管理就会从一次性操作变成持续治理问题。一个典型分片集群里,配置面至少包含四类对象:每个 mongod/mongos 进程的 mongod.conf 文件、分片标签(shard tag)、区域分片(zone sharding)规则,以及配置服务器(config server)副本集的运行参数。它们分别控制进程行为、数据放置策略和元数据一致性,任何一处手工漂移都可能引发节点重启失败、数据分布倾斜或元数据读写异常。因此,本节的核心不是“会改配置”,而是用自动化工具把配置变成可版本化、可校验、可回滚的声明式资产。
一、mongod.conf 的自动化管理
mongod.conf 采用 YAML 格式,分片集群中每个节点的差异主要来自 sharding.clusterRole、replication.replSetName、net.port、storage.dbPath 和 setParameter 等字段。手工逐台修改的问题在于:节点数量多、字段易漏、重启后才发现语法错误。自动化管理的基本做法是“模板 + 变量 + 校验 + 分发”。
以 Ansible 为例,可先定义一份 Jinja2 模板,把节点角色作为变量注入:
# templates/mongod.conf.j2
net:
port: {{ mongo_port }}
bindIp: {{ bind_ip }}
storage:
dbPath: {{ db_path }}
wiredTiger:
engineConfig:
cacheSizeGB: {{ cache_size_gb }}
replication:
replSetName: {{ replset_name }}
sharding:
clusterRole: {{ cluster_role }} # shardsvr | configsvr
setParameter:
enableLocalhostAuthBypass: false
diagnosticDataCollectionEnabled: true
变量文件按角色分组,例如 group_vars/shard_nodes.yml 中设置 cluster_role: shardsvr、replset_name: shard01,group_vars/config_nodes.yml 中设置 cluster_role: configsvr、replset_name: cfgRepl。分发前必须做两件事:一是用 mongod --config /tmp/mongod.conf --configCheck 做语法与参数校验,二是用 diff 或 Ansible 的 --check 模式预演变更。只有校验通过才允许写入目标路径并触发滚动重启。滚动重启的顺序应遵循“先从节点、后主节点”,并借助副本集选举保证服务不中断。
mongod.conf 纳入 Git 仓库,每次变更提交都记录变更原因、影响节点和回滚命令。配置文件的版本历史,往往比进程日志更能解释一次故障的根因。二、分片标签与区域分片
分片标签是给分片打的逻辑标记,区域分片则是“标签 + 分片键范围”的组合规则。它们共同决定哪些数据必须落在哪些分片上。自动化管理的关键是把“标签定义”和“范围绑定”都写成幂等脚本,而不是在 mongos 里临时敲命令。
假设一个订单集群有三个分片 shard01、shard02、shard03,业务要求华东数据留在 shard01、华南数据留在 shard02、华北数据留在 shard03。分片键为 { region: 1, orderId: 1 }。自动化脚本可按如下顺序执行:
// 1. 打标签
sh.addShardTag("shard01", "east");
sh.addShardTag("shard02", "south");
sh.addShardTag("shard03", "north");
// 2. 绑定区域范围(注意:范围必须覆盖分片键的完整取值空间)
sh.addTagRange("shop.orders", { region: "east", orderId: MinKey }, { region: "east", orderId: MaxKey }, "east");
sh.addTagRange("shop.orders", { region: "south", orderId: MinKey }, { region: "south", orderId: MaxKey }, "south");
sh.addTagRange("shop.orders", { region: "north", orderId: MinKey }, { region: "north", orderId: MaxKey }, "north");
这里有两个容易出错的点。第一,区域范围必须连续且不重叠,否则会出现“无标签可落”的文档,导致写入被阻塞或均衡器反复迁移。第二,addTagRange 只对已存在的集合生效,若集合尚未分片,需要先 sh.enableSharding 并 sh.shardCollection。自动化工具应在执行前查询 config.tags 和 config.chunks,对比期望状态与实际状态,只下发差异部分,避免重复添加造成报错。
三、配置服务器参数管理
配置服务器副本集保存集群的全部元数据,包括分片、块、标签和集合路由信息。它的参数调整比普通分片更敏感,因为一旦配置服务器不可写,整个集群的路由信息就无法更新。自动化管理配置服务器参数时,应遵循“小步、可观测、可回滚”的原则。
常见需要关注的参数包括:writeConcernMajorityJournalDefault(影响元数据写入的持久性)、setParameter.enableMajorityReadConcern(影响读一致性)、以及 setParameter.periodicNoopIntervalSecs(影响心跳与选举节奏)。修改方式有两种:一是改 mongod.conf 后滚动重启,二是通过 replSetSetParameter 在线调整。前者适合启动参数,后者适合运行期参数。无论哪种方式,都应先在一台从节点验证,再推广到整个副本集。
// 在线调整配置服务器副本集参数(示例)
db.adminCommand({
setParameter: 1,
periodicNoopIntervalSecs: 2
});
// 查看当前生效值
db.adminCommand({ getParameter: 1, periodicNoopIntervalSecs: 1 });
自动化工具在执行这类变更时,应记录变更前后的参数快照,并在变更后检查 rs.status() 中配置服务器副本集的健康状态,确认没有节点处于 RECOVERING 或 ROLLBACK 状态。
四、把四类配置纳入同一套治理流程
mongod.conf、分片标签、区域分片和配置服务器参数虽然形态不同,但治理逻辑可以统一为四个动作:声明、校验、下发、核对。声明阶段把期望状态写入 Git;校验阶段检查语法、范围和权限;下发阶段只改差异并控制重启节奏;核对阶段用 rs.status()、sh.status()、db.adminCommand({getParameter:1}) 等命令确认实际状态与期望一致。
需要特别提醒的是,区域分片和分片标签的变更会触发块迁移,属于“有数据流动”的操作。自动化脚本在执行前应评估迁移量,尽量避开业务高峰;执行后要观察 sh.getBalancerState() 和 db.currentOp(),确认均衡器没有长时间卡在迁移任务上。配置服务器参数的在线调整虽然不迁移数据,但可能影响选举和心跳,同样需要选择低峰窗口。
最后,建议为每次配置变更保留一份最小审计记录:变更时间、操作人、涉及对象、变更前后差异、校验命令与结果、回滚命令。这份记录不需要复杂系统,一个 Git 提交加上一段变更说明即可。当集群出现路由异常或数据分布倾斜时,它能快速回答“最近改了什么”,这比事后逐台登录排查高效得多。