You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

高并发场景下Mongoose写入MongoDB异常问题求助

高并发场景下Mongoose插入性能异常排查与解决思路

问题场景

  • 压测架构:mock.js 通过socket.io每秒向server.js推送10K条数据,server.js异步调用db.js,通过Mongoose向MongoDB执行单条插入
  • 预期表现:Mongoose创建数百个MongoDB连接,每秒完成约9K次插入
  • 异常表现:
    • 压测期间MongoDB仅产生数十次插入、维持约10个连接,无明显响应
    • 停止压测后,MongoDB插入量和连接数瞬间飙升,直至完成所有积压操作
    • 持续压测会导致server.js先OOM,之后MongoDB才开始处理请求

核心原因分析

  1. Mongoose连接池默认限制
    Mongoose默认连接池大小(maxPoolSize)仅为10,高并发下单条插入请求会被阻塞在连接池队列中,无法及时发送到MongoDB,导致请求在server.js内存中大量积压,最终引发OOM。
  2. 单条插入的低效性
    每秒10K条单条插入会产生大量网络往返和事务开销,即使连接池足够大,单条插入的吞吐量也远低于批量插入,无法匹配压测的请求速率。
  3. 请求积压的连锁反应
    压测期间请求持续涌入,但MongoDB处理能力跟不上,所有未处理的请求会在server.js内存中排队,内存占用持续升高直至OOM;停止压测后队列中的请求才会被批量发送到MongoDB,导致插入量和连接数瞬间飙升。

针对性解决方法

1. 调整Mongoose连接池配置

显式增大连接池大小,同时设置合理超时参数,避免请求长时间积压:

// db.js 中的连接配置
mongoose.connect('mongodb://localhost:27017/yourDB', {
  maxPoolSize: 150, // 根据服务器CPU核心数和MongoDB承载能力调整,建议100-200
  socketTimeoutMS: 30000,
  connectTimeoutMS: 30000
});

2. 改用批量插入替代单条插入

将请求攒成批量后提交,大幅减少网络往返次数,这是提升插入吞吐量最有效的方式:

// db.js 中实现批量插入逻辑
let batchBuffer = [];
const BATCH_SIZE = 1000; // 每攒够1000条提交一次,可根据实际调整

async function insertData(data) {
  batchBuffer.push(data);
  if (batchBuffer.length >= BATCH_SIZE) {
    const currentBatch = [...batchBuffer];
    batchBuffer = [];
    try {
      await YourModel.insertMany(currentBatch, { ordered: false }); // ordered: false 允许部分失败不中断整体
    } catch (err) {
      console.error('批量插入失败:', err);
      // 可额外记录失败的数据,后续重试
    }
  }
}

// 程序退出时提交剩余缓冲数据
process.on('exit', async () => {
  if (batchBuffer.length > 0) {
    await YourModel.insertMany(batchBuffer, { ordered: false });
  }
});

3. 控制请求流入速率

在server.js中对socket.io请求做限流,避免接收超出处理能力的请求,从源头防止内存积压:

// server.js 中实现socket限流
const socketIoLimiter = require('socket.io-rate-limiter');

const limiter = socketIoLimiter({
  max: 10000, // 每秒最多处理10K条,根据实际处理能力调整
  duration: 1000
});

io.on('connection', (socket) => {
  limiter(socket);

  socket.on('data', async (data) => {
    await insertData(data);
  });
});

4. 排查事件循环阻塞

用node --trace-event-categories v8,node.async_hooks启动服务,排查是否存在同步计算、IO阻塞等操作,确保异步插入请求能及时进入事件循环处理。

内容的提问来源于stack exchange,提问作者OlderFox

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 20:57:21