1. 分片集群架构总览

当单机 MongoDB 或单个副本集已经无法承载数据量或写入压力时,分片集群(Sharded Cluster)就是 MongoDB 提供的水平扩展方案。它的核心思想并不复杂:把一份逻辑上的大集合,按照某个规则切成若干份,分散到多台机器上,每台机器只负责其中一部分数据。但要让这套机制对应用透明、对运维可控,MongoDB 引入了几个职责明确的组件,它们共同构成了分片集群的骨架。

三个核心组件

mongos(路由进程)是应用唯一需要连接的入口。它本身不存储数据,只负责解析查询、向配置服务器获取元数据、把请求转发到正确的分片,再把各分片返回的结果合并后交给客户端。对应用来说,连接 mongos 和连接一个普通 mongod 几乎没有区别,分片的存在被完全隐藏。生产环境通常部署多个 mongos,应用通过负载均衡或驱动层的多主机连接串分散请求。

config server(配置服务器)保存整个集群的元数据:有哪些分片、每个集合的分片键是什么、每个数据块(chunk)落在哪个分片上、集群的均衡状态等。从 MongoDB 3.4 起,配置服务器本身也必须是一个副本集(CSRS),以保证元数据的高可用。元数据一旦丢失或不可用,整个集群将无法路由请求,因此配置服务器的稳定性优先级最高。

shard(分片)是真正存储数据的单元。每个分片在物理上都是一个副本集,而不是单个 mongod。这一点常被初学者忽略:分片解决的是“数据太多、写入太猛”的横向扩展问题,副本集解决的是“单点故障、高可用”问题,两者是叠加关系而非替代关系。一个分片内部仍然有主节点和从节点,仍然通过 oplog 复制。

应用程序 / Driver 连接串 mongos 路由进程 解析查询 · 获取元数据 · 转发 · 合并结果 读取元数据 路由请求 Config Server 副本集 chunk 分布 · 分片键 · 集群状态 Shard 1(副本集) P S S chunk A · chunk D P=Primary S=Secondary Shard 2(副本集) P S S chunk B · chunk E P=Primary S=Secondary Shard 3(副本集) P S S chunk C · chunk F P=Primary S=Secondary Balancer 在分片间迁移 chunk

数据分布原理:分片键与 chunk

数据如何切分,取决于分片键(shard key)。分片键是集合中一个或一组不可变字段,MongoDB 用它计算每条文档属于哪个 chunk。chunk 是一段连续的分片键取值区间,默认大小 64MB。当 chunk 增长超过阈值,MongoDB 会将其一分为二;当各分片上的 chunk 数量差距超过迁移阈值,均衡器(balancer)会把 chunk 从多的分片搬到少的分片。

分片键的选择直接决定集群能否真正扩展。以订单集合为例,若用 { orderId: "hashed" } 做哈希分片,写入会均匀打散到所有分片,适合高并发写入;但按时间范围查询会退化为广播到所有分片。若用 { userId: 1, orderTime: 1 } 做范围分片,同一用户的订单落在同一 chunk,按用户查询效率高,但若 userId 分布不均,可能出现热点分片。这是分片集群最核心的权衡:写入均匀性与查询局部性往往不可兼得。

与副本集的对比

维度副本集分片集群
扩展方向垂直扩展(提升单机配置)水平扩展(增加分片数量)
数据容量受单机磁盘限制理论上无上限,随分片增加
写入能力受主节点单点写入限制多分片并行写入,线性提升
高可用主节点故障自动切换每个分片内部仍是副本集,叠加高可用
运维复杂度较低较高,需管理 mongos、config、均衡
查询延迟单跳访问可能跨分片合并,延迟略高

适用场景与选型决策

分片集群不是默认选项,它带来扩展能力的同时也带来复杂度。以下情况应优先考虑分片:单集合数据量预计超过单机磁盘容量;写入吞吐持续接近单副本集上限;需要按地理区域就近部署数据。反之,如果数据量在几百 GB 以内、写入压力可控,一个三节点副本集往往更简单、更稳定。

选型时先问三个问题:数据总量会不会超过单机磁盘?写入 QPS 会不会打满单主节点?查询模式是否允许分片键带来的路由约束?三个问题中有两个以上为“是”,再考虑分片集群。

一旦决定分片,部署顺序也有讲究:先搭建 config server 副本集,再启动 mongos 并指向 config,最后逐个添加 shard 副本集。分片键应在集合创建时或数据量较小时确定,因为分片键不可更改,后期更换需要重建集合并迁移数据,代价极高。

分片键一旦选定便不可修改。若业务初期无法确定,可先用哈希分片保证写入均匀,再通过查询模式评估是否需要调整。切勿在数据量达到 TB 级后才重新设计分片键。

理解这三个组件的职责边界,是后续学习分片键设计、chunk 均衡、查询路由和故障排查的基础。分片集群的复杂度不在于单个组件,而在于它们之间的协作关系:mongos 依赖 config 的元数据,config 记录 shard 的状态,shard 之间通过 balancer 保持均衡。任何一环异常,都会在查询路径上体现出来。