默认读请求路由到各分片主节点,因mongos转发客户端readPreference且副本集默认为primary;无分片键查询会广播至所有分片主节点,加剧负载;需同时满足明确设置readPreference、命中分片键、secondary健康可用三条件才能分流。

默认情况下,MongoDB分片集群的读请求确实会路由到每个分片内的主节点(primary),这不是 bug,而是由两个独立但叠加的机制共同决定的:分片路由逻辑 + 副本集读取偏好。
mongos 默认不改写客户端的读取偏好
当应用连接 mongos 并发起一个读操作时,mongos 本身不强制指定读取偏好;它只是把客户端传来的读取偏好原样转发给目标分片。如果客户端没显式设置 readPreference(比如用 Node.js 驱动未配置 readPreference: 'secondary'),驱动就会使用默认值 'primary' —— 这个值作用于副本集层级,不是分片层级。
- 也就是说,
mongos不是“选择主节点”,而是“把读请求发给分片,由分片自己按readPreference决定去哪个成员读” - 即使你在连接字符串里写了
?readPreference=secondary,也只对直连副本集有效;对接mongos时,该参数会被传递下去,但最终是否生效,取决于每个分片内部的副本集是否允许、是否有可用的secondary - 若某分片当前只有
primary在线(比如一个三节点副本集挂了两个secondary),那么readPreference: 'secondary'会静默退化为primary,不会报错也不会阻塞
分片键缺失导致广播查询,加剧主节点压力
当查询不含分片键(或其前缀)时,mongos 必须执行广播操作:把请求发给所有分片。每个分片再各自按自己的 readPreference 执行。结果就是:N 个分片 × 每个都打到自己的 primary → 主节点集群整体负载飙升。
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
- 典型场景:分页查询没带
shard key、聚合管道开头没 $match 到分片键、或使用了$text/$regex等无法下推的条件 - 这类查询在
explain()输出中会显示"executionStages": { "stage": "SHARD_MERGE" },且"shards"数组里列出全部分片 - 即使你设了
readPreference: 'nearest',广播本身已让延迟和负载失去优化意义
配置节点只读、secondary 节点不可用等隐性 fallback
某些看似“应该走 secondary”的读请求,实际仍落到 primary,往往是因为底层条件不满足:
- 副本集里没有健康且可读的
secondary:比如节点状态为RECOVERING、STARTUP2,或被标记为hidden: true/priority: 0 - 设置了
maxStalenessSeconds,但某个secondary的 oplog 落后超过阈值(例如主节点写入激增,从节点同步延迟达 30s,而你设了maxStalenessSeconds: 10) - 配置服务器副本集降级为只读(如主配置节点宕机且无法选出新主),此时
mongos可能拒绝某些元数据变更类读操作,但普通数据读仍走各分片,而各分片若检测到配置异常,也可能收紧读策略
真正想让读流量分散到从节点,不能只靠改一个参数。得确认三点:客户端明确设置了 readPreference,查询能命中分片键以避免广播,且每个分片的副本集里有至少一个满足 tags、maxStalenessSeconds 和状态要求的 secondary。少一个,流量就悄悄回到 primary。


















