config server存储分片集群的元数据(如chunk分布、shard列表、balancer状态等),而非业务数据,是mongos路由查询的“导航地图”;必须以三节点副本集(csrs)部署,启用--configsvr参数,禁止手动修改config库。

Config Server到底存什么?不是数据,是“地图”
Config Server不存业务数据,只存整个分片集群的元数据——也就是所有数据块(chunk)在哪台shard、范围是多少、当前balancer是否在跑、chunksize设为多少等。它相当于集群的“导航地图”,mongos每次路由查询或写入前,都得先查它才知道该找哪个分片。
常见错误现象:mongos启动失败报 Failed to load clusterID from config server,或客户端连上后查不到库/集合,大概率是 config server 没起来,或三个节点间副本集状态没同步好(比如一个节点还在 STARTUP2 状态)。
- 关键元数据集合都在
config数据库里:config.shards(分片列表)、config.chunks(每个 chunk 的范围和归属)、config.mongos(活跃路由节点心跳)、config.settings(如{"_id":"balancer","stopped":false}) - 从 MongoDB 3.4 起,
config server必须以副本集形式部署(CSRS),单节点直接被拒绝启动;3.2 是过渡期,支持但不强制 - 不要手动往
config库里插数据——哪怕只是想“临时改个 chunksize”,必须用sh.setShardingKey()或sh.splitAt()等官方 shell 命令,否则极易导致元数据不一致
为什么必须是三个节点?不是高可用那么简单
三个 config server 节点不是为了“多一副本更稳”,而是为了满足副本集选举 + 元数据强一致性双重约束:少于三节点无法容忍单点故障(两节点时网络分区会导致脑裂,无法达成多数派写入);多于三节点又会显著拖慢 mongos 读取元数据的延迟——因为每次路由都要从 majority 节点读最新配置。
- 典型部署模式:三个节点跨至少两个物理位置(比如机房A两台 + 云上一台),避免单数据中心整体宕机导致 config 不可用
- 如果硬要压缩成本,宁可两节点+仲裁者(
arbiter),也绝不能只用两个数据节点——仲裁者不存数据,但能参与投票,且资源开销极小 - 注意:仲裁者不能部署在和某个
config主节点同一台机器上,否则该机器宕机 = 投票权+数据同时丢失
config server 和普通 shard 副本集,启动参数差在哪?
本质区别就一个:--configsvr 参数。它不只是“打个标签”,而是让 mongod 进程自动绑定到默认端口 27019、限制只接受来自 mongos 的元数据操作、禁用部分用户管理命令(比如 createUser 在 config server 上默认被拒)。
常见错误:用 --shardsvr 启动 config server,结果 mongos 死活连不上,日志里反复出现 unable to reach config server —— 因为端口错、角色错、权限错,三重不匹配。
- 正确启动命令示例:
mongod --configsvr --replSet configRepl --dbpath /data/config --port 27019 - 别试图用
--port 27017替代--configsvr:虽然能跑起来,但 mongos 会拒绝连接(协议校验失败) - config server 副本集名称(
--replSet)必须全局唯一,且不能和任何 shard 的 replica set 名称重复,否则 mongos 初始化时解析混乱
mongos 性能瓶颈常藏在 config server 身上
很多人调优只盯着 mongos 内存和 CPU,却忽略它每秒可能向 config server 发起数十次元数据读请求(尤其开启 balancer 或频繁增删分片时)。一旦 config server 副本集主节点磁盘 I/O 高或网络延迟抖动,mongos 就会卡在元数据加载阶段,表现为查询响应时间突增、偶发超时。
- 监控重点不是
mongos自身,而是config副本集的lastApplied和optimeDate差值——超过 5 秒就说明从节点严重滞后,影响故障切换 - 生产环境建议给 config server 单独划 SSD 存储,且
dbPath不要和 shard 共用同一块盘 - 如果集群规模大(>50 个 mongos 实例),考虑在 config server 前加一层轻量代理(如 HAProxy TCP 模式),做连接复用和健康检查,而不是让每个 mongos 直连所有三个 config 节点
最易被忽略的一点:config server 副本集初始化后,必须执行 rs.initiate() 并等待状态变为 PRIMARY,再启动 mongos;跳过这步,mongos 会一直卡在 “waiting for config server” 状态,而日志里未必报错——它只是安静地等,等得你怀疑人生。










