真正起效的是控制数据流向、压紧网络路径、调优tcp栈和wiredtiger缓存四件事;zone sharding需分片键含zone字段、副本集全量部署同机房并打tags、mongos与应用同机房;tcp缓冲区与窗口缩放必须调大,dns和连接池需优化,gridfs延迟源于oplog复制链路而非心跳参数。

跨机房网络延迟不能靠调心跳或开 tcp_fastopen 解决,真正起效的是控制数据流向、压紧网络路径、调优 TCP 栈和 WiredTiger 缓存四件事。
Zone Sharding 必须配齐三要素才生效
光在 config server 上执行 addShardToZone 和 updateZoneKeyRange 不够。常见错误是分片键没包含 Zone 字段,或者 mongos 和 shard 不在同机房。
- 分片键必须含 Zone 字段(如
{region: 1, _id: 1}),否则 mongos 无法根据查询条件路由到对应 zone - 每个 shard 的副本集必须完整部署在目标机房,且通过
rs.reconfig()在members[n].tags中显式标记(如{"region": "shanghai"}) - 客户端连接的 mongos 必须和应用同机房;如果应用在北京、mongos 却在上海,所有请求先绕到上海再转发,必然跨机房
TCP 缓冲区和窗口缩放必须调大
跨机房链路 RTT 高(通常 >50ms),默认 TCP 窗口(64KB)会严重限制带宽利用率,导致 oplog 复制吞吐卡死。
-
net.ipv4.tcp_rmem和net.ipv4.tcp_wmem设为"4096 65536 16777216"(即 max=16MB) -
net.ipv4.tcp_window_scaling必须为1,否则窗口无法突破 64KB -
net.core.somaxconn和net.core.netdev_max_backlog至少设为65535和5000,防 heartbeat 和 oplog fetch 排队丢包 - 改完后用
ss -i -t -n | grep :27017确认 mongod 进程 socket 实际接收/发送缓冲区是否生效
mongos 路由层延迟要从 DNS 和连接池掐住
mongos 到 shard 的单次请求延迟,常被误认为是复制延迟,其实是路由决策慢——DNS 解析卡顿、连接池打满、跨 AZ 路径绕行都会放大它。
- 启动 mongos 时禁用域名解析:用
--bind_ip 127.0.0.1+ 配置文件中直接写死 shard 的内网 IP,别用域名 - 若必须用域名,确保 DNS 只返回 A 记录,在
/etc/gai.conf加precedence ::ffff:0:0/96 100禁 IPv6 回退 -
--maxConnsPerHost 200和--minConnsPerHost 10防冷启动空池;同时检查 shard 端net.maxIncomingConnections是否足够 - 用
db.adminCommand({ "connPoolStats": 1 })查 mongos 当前连接分布,确认是否有 shard 连接长期占满
GridFS 同步延迟别碰 heartbeatIntervalMillis
把 heartbeatIntervalMillis 从 2000 改成 500 毫秒,对 GridFS 文件同步延迟零影响,反而增加心跳流量和误判风险。
- GridFS 延迟 = oplog 复制链路耗时,盯
rs.status().members[n].optimeDate和主节点差值,>5s 就查网络或磁盘 - 从节点关 journal(
--nojournal)减 fsync 压力;oplogSize 至少设为20480(20GB)防覆盖 - 删掉从节点
fs.chunks上除{files_id: 1, n: 1}外的所有索引,避免迁移时写放大 - 避免在从节点调
bucket.openDownloadStreamByName(),它内部 fallback 到 primary 查元数据,跨机房多一次 RTT
最难处理的不是参数怎么调,而是当 oplog 复制卡住时,rs.printSecondaryReplicationInfo() 显示 lag 持续上涨却查不到源头——这时候得翻 mongod.log 里 moveChunk 或 oplog application 的 timestamp gap,而不是反复改心跳或 TFO。











