← 返回题目列表

MongoDB 分片是什么?Shard Key 应该怎么选?

高频 困难 第 17 / 31 题 更新于 2026/07/28
MongoDB分片Shard Key水平扩展

简化版

MongoDB 分片是把一个集合的数据按 shard key 拆分到多个 shard 上,实现水平扩展。Shard Key 选择非常关键,要兼顾高基数、写入分布均匀、查询可定向路由、避免热点和 jumbo chunk。选错 shard key 会导致数据倾斜、单分片热点、跨分片查询变多,后期调整成本很高。

详细版

分片集群主要组件:

  • Shard:实际存储数据的分片;
  • Mongos:查询路由;
  • Config Server:保存集群元数据;
  • Shard Key:决定文档分布和查询路由;
  • Chunk:数据迁移和平衡的基本范围。

好的 shard key 通常具备:

  • 高基数:不同取值足够多;
  • 低频重复:不会大量数据集中到一个值;
  • 写入分散:避免所有写入打到一个分片;
  • 查询常带:让查询能定向到少数分片;
  • 不容易变更:分片键变更成本高。

完整版教学

一、为什么需要分片

当单个副本集无法承载数据量或吞吐时,需要水平扩展。分片把数据拆到多个 shard,每个 shard 负责一部分数据。

可以理解为:

集合 orders
  ├── shard1: 一部分订单
  ├── shard2: 一部分订单
  └── shard3: 一部分订单

这样存储和读写压力可以分摊。

二、Mongos 负责路由请求

应用通常连接 mongos。Mongos 根据查询条件和 config server 中的元数据判断请求应该发往哪些 shard。

如果查询带 shard key:

db.orders.find({ userId: 100 })

可能只路由到目标 shard。

如果查询不带 shard key,就可能广播到多个 shard,这叫 scatter-gather,成本更高。

三、Shard Key 是分片成败的核心

Shard Key 决定数据怎么分布,也决定查询能否定向。

如果选择递增字段如纯时间戳或自增 ID,写入可能总是落到最后一个范围,形成写热点。

如果选择低基数字段如性别、状态,数据会集中到少数取值,分布不均。

所以 shard key 不是随便选一个查询字段,而是要综合写入分布和查询路由。

四、范围分片和哈希分片怎么取舍

范围分片适合范围查询,例如按时间范围查询。但如果写入键单调递增,容易产生热点。

哈希分片可以让写入更均匀,但范围查询可能要访问多个 shard。

取舍思路:

  • 范围查询很重要:考虑范围分片或复合键;
  • 写入均匀更重要:考虑哈希分片;
  • 既要过滤业务维度又要分散写入:考虑复合 shard key;
  • 不要只看当前数据量,要看未来增长。

五、分片不是自动解决所有慢查询

分片能扩展容量和吞吐,但如果查询不能定向,反而可能更慢。

常见问题:

  • 查询不带 shard key,广播所有分片;
  • shard key 选择导致数据倾斜;
  • 热点用户或热点租户集中;
  • chunk 无法正常拆分或迁移;
  • 跨分片聚合和事务成本高。

分片前要先确认单机索引、查询、建模已经优化过。

六、Chunk 和均衡迁移决定运维成本

MongoDB 分片不是简单把数据平均切成几份,它通过 chunk 管理数据范围,并由 balancer 在 shard 之间迁移 chunk。Shard key 的分布会直接影响 chunk 是否能正常拆分、迁移和均衡。

Shard Key 问题可能后果例子
低基数少数 chunk 过大status 只有 3 个取值
单调递增写入集中到尾部 chunk时间戳、自增 ID
热点实体单 shard 请求过载头部租户、热门商家
查询不带 shard key广播查询全站按状态查订单

假设集合有 9 亿文档,分到 3 个 shard,理想状态每个 shard 约 3 亿;但如果 shard key 是 tenantId,某个大租户占 4 亿文档,它所在 shard 就会明显倾斜。分片设计必须同时看数据量分布和请求量分布。

七、常见误区与追问

带 shard key 查询:
mongos -> 定位目标 shard -> 单 shard 查询

不带 shard key 查询:
mongos -> 广播多个 shard -> 汇总结果

记忆钩子:好 shard key 要同时满足三个动作:写得散、查得准、迁得动。

  • 误区:分片后所有查询都会变快。 不带 shard key 的查询可能广播到所有 shard,再汇总排序,复杂度反而更高。
  • 误区:高基数字段一定适合做 shard key。 高基数只是条件之一,还要看查询是否常带、写入是否均匀、是否存在热点实体。
  • 误区:哈希分片没有任何缺点。 哈希能分散写入,但范围查询和按时间归档可能需要访问多个 shard。
  • 追问:为什么递增 shard key 容易热点? 新写入总落到最新范围 chunk,导致某个 shard 承担大部分写压力。
  • 追问:什么是 scatter-gather? 查询无法定向到单个 shard 时,mongos 向多个 shard 发请求并聚合结果,延迟和资源成本更高。
  • 追问:Shard key 选错后好改吗? 成本很高,可能涉及重分片、迁移、索引、停机或长时间双写校验,所以前期评估非常关键。

八、加强记忆

MongoDB 分片的核心是 shard key。好 shard key 要让数据分得开、写入散得开、查询找得到;坏 shard key 会让分片集群变成更复杂的单点瓶颈。分片解决水平扩展,不替代索引和建模优化。