YCSB吞吐量上不去但CPU低,主因是客户端单线程/单连接瓶颈及mongos路由集中,需调高threadcount、connections.per.host,禁用socketKeepAlive,并多mongos地址实现负载均衡。

用 YCSB 压测时,为什么吞吐量上不去但 CPU 很低?
这不是 MongoDB 本身卡住了,而是客户端或网络层成了瓶颈。YCSB 默认单线程、单连接发请求,对分片集群完全无效——所有请求都挤在同一个 mongos 上,还可能被本地 DNS 缓存或连接复用“粘住”。
必须显式启用并发和连接池:
- 加
-p threadcount=64或更高,避免单线程压不起来 - 用
-p mongodb.connections.per.host=16控制每个 mongos 的连接数,防止连接耗尽 - 禁用
-p mongodb.socketKeepAlive=false,否则 TCP 复用会掩盖真实连接压力 - 连接字符串里写多个 mongos 的 DNS 名(如
mongodb://mongos-a,mongos-b/?localThresholdMS=15),靠客户端负载均衡打散流量
mongoreplay 重放时写入延迟突增,config server 日志却没报错
这是典型的元数据锁竞争,不是 config server 挂了,而是它被高频 chunk 查询拖慢了。尤其当片键是时间戳或 _id 自增字段时,新写入总落在同一 chunk 尾部,mongos 每次都要查 config server 确认路由,而 config server 是单点 WiredTiger 实例,不支持分片。
验证方式很简单:
当代理已经知道网站路由或内容URL,并且在启动前需要有效的sitemap XML、sitemap索引或robots.txt引用时,请使用sitemap。这是一个发布构件技能,而不是爬虫或SEO平台。
- 运行
mongotop --host <config-server-addr>,看config.chunks表的 read time 是否持续高于其他表 - 在 config server 上执行
db.currentOp({secs_running: {$gt: 1}}),找长时间阻塞的find操作 - 临时把写入改成哈希分片(
sh.shardCollection("db.coll", {"_id": "hashed"})),如果延迟立刻下降,基本坐实问题
YCSB 报 Operation timed out,但 mongostat 显示 connections 正常
超时往往不是数据库拒绝连接,而是驱动层在等响应时被网络或 TLS 握手拖住。PHP、Java 驱动默认 socket 超时很短,YCSB 的 socketTimeoutMS 又没透传过去。
关键要调三处:
- YCSB 启动参数加
-p mongodb.socketTimeoutMS=30000 - 确保 mongos 配置里
net.maxIncomingConnections足够(至少 2000) - 检查操作系统级限制:
ulimit -n必须 ≥ 所有 mongos 连接数总和,否则内核直接丢包 - Rocky 8.6 和 CentOS 7.9 在透明大页(THP)默认行为不同,Rocky 8.6 开启 THP 更激进,务必确认
/sys/kernel/mm/transparent_hugepage/enabled是never
压测中发现读延迟波动大,但索引命中率 100%
索引有效 ≠ 性能稳定。WiredTiger 缓存抖动、跨分片查询、或者从节点读取时主从延迟未控,都会导致延迟毛刺。
先定位来源:
- 用
db.runCommand({currentOp: 1, secs_running: {$gt: 0.5}})查看慢操作是否集中在某个分片 - 强制走主节点读:
readPreference=primary,如果波动消失,说明是 secondary 数据陈旧或负载不均 - 开 profiling:
db.setProfilingLevel(1, {slowms: 50}),再查system.profile,注意millis和nreturned是否成正比——不成正比大概率是网络或 mongos 路由开销 - 检查 chunk 分布:
sh.status()看各分片 chunk 数是否均衡,严重倾斜会导致部分分片独占高负载
wiredTiger.engineConfig.cacheSizeGB,它就会悄悄拖垮整个集群的写入路径。


















