Zone特性需手动绑定分片标签与数据范围,是唯一可控冷热分离路径;须用mongos连接、clustermanager权限,标签名区分大小写,键范围须严格匹配shard key结构并用MinKey/MaxKey占位,哈希分片需换算真实哈希值,范围不可重叠,存量数据迁移依赖sh.moveChunk()且需开启balancer。

Zone特性不能自动识别硬件类型,必须手动绑定分片标签与数据范围——这是唯一可控的冷热分离路径。
sh.addShardTag() 给分片打标签时容易漏掉权限或连接点
你得用 mongos 连接(不是直接连 mongod),且用户必须有 clustermanager 角色。常见错误是:sh.addShardTag("shard01","SSD") 执行失败却没报权限错,其实是连错了节点。
- 确认当前连接的是
mongos:运行db.runCommand({isMaster: 1}),返回里要有"msg" : "isdbgrid" - 检查权限:
db.getUsers({filter: {roles: {$elemMatch: {role: "clustermanager"}}}}) - 标签名区分大小写,
"ssd"和"SSD"是两个不同 zone
sh.updateZoneKeyRange() 的键范围必须严格匹配 shard key 结构
比如 shard key 是 {created_at: 1, event_type: 1},那 updateZoneKeyRange 的范围也必须是两字段对象,不能只写 {created_at: ISODate("2025-01-01")} —— 否则命令静默失败,数据仍路由到默认分片。
- 范围边界必须用
MinKey/MaxKey占位,不能用null或空对象 - 哈希分片键要用
convertShardKeyToHashed()算出真实哈希值再设范围,否则范围无效 - 范围不能重叠,MongoDB 不校验重叠,但 balancer 会拒绝迁移违反 zone 约束的 chunk
数据不会自动迁移到新 zone,moveChunk 是绕不开的手动操作
设置好 zone 后,已存在的 chunk 不会自己挪过去。balancer 默认忽略 zone 约束,除非你先调用 sh.enableSharding("db") 并确保 sh.setBalancerState(true) 已开启。
- 存量数据迁移必须用
sh.moveChunk(),例如:sh.moveChunk("db.collection", {created_at: ISODate("2024-01-01")}, "shard01") - 迁移期间 chunk 会被锁定,写入暂停,大集合建议在低峰期执行
- 如果 chunk 太大(比如 >128MB),先用
sh.splitAt()切小再 move,避免超时
真正难的不是配置命令,而是判断哪些数据该归 SSD、哪些归 HDD——MongoDB 不提供访问热度指标,你得靠业务日志或监控系统反推时间窗口,然后反复调整 updateZoneKeyRange 范围。一旦 shard key 选得窄(比如只用 {status: 1}),整个 zone 策略就失效,因为 chunk 根本切不开。

















