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

Firebase批量写入25k文档是否触达每秒写入上限?如何限流?

嗨,作为新手能考虑到性能限制这点真的很棒!咱们一步步来拆解你的问题:

一、原代码会触发Firebase写入上限吗?

答案是肯定会。Promise.all(promises)会尽可能并行发起所有25000个写入请求,Firebase Firestore的写入限制是每秒最多10000次操作,这意味着你的代码会在极短时间(远小于1秒)内发起远超上限的请求,最终会导致部分写入失败、被限流,甚至可能触发Firebase的安全机制阻断后续请求。

二、如何把操作分散到不同时间段?

最适合新手的方案是分批处理+延迟间隔,结合Firebase的批量写入API还能进一步优化性能。下面给你两种具体实现方式:

方式1:简单分批并行处理

把25000个用户分成每批9000个(留1000的余量避免触顶),每批处理完后等待1秒以上再处理下一批:

const query = db.collection(`users`) 
  .where("lastActivity","<=",now) 
  .where("lastActivity",">=",last30Days);
const usersQuerySnapshot = await query.get();
const userDocs = usersQuerySnapshot.docs;

// 每批处理9000个,低于10000的上限
const batchSize = 9000;

for (let i = 0; i < userDocs.length; i += batchSize) {
  // 截取当前批次的用户文档
  const currentBatchDocs = userDocs.slice(i, i + batchSize);
  const promises = [];

  currentBatchDocs.forEach(userSnapshot => {
    const user = userSnapshot.data();
    const userID = user.userID;
    const p1 = db.doc(`users/${userID}/inbox/${notificationID}`).set(notificationData);
    promises.push(p1);
  });

  // 等待当前批次所有写入完成
  await Promise.all(promises);

  // 如果不是最后一批,等待1.1秒再继续(多留100ms确保不超限制)
  if (i + batchSize < userDocs.length) {
    await new Promise(resolve => setTimeout(resolve, 1100));
  }
}

return "所有通知已发送完成";

方式2:结合Firebase批量写入(更高效)

Firebase的Batch API允许一次请求处理最多500个写入操作,能大幅减少网络请求次数,同时更容易控制速率。我们可以每20个Batch(对应10000次写入)后等待1秒:

const query = db.collection(`users`) 
  .where("lastActivity","<=",now) 
  .where("lastActivity",">=",last30Days);
const usersQuerySnapshot = await query.get();
const userDocs = usersQuerySnapshot.docs;

const maxBatchOperations = 500; // Firebase Batch单次最大操作数
const batches = [];
let currentBatch = db.batch();
let operationCount = 0;

// 先把所有写入操作分配到不同的Batch中
userDocs.forEach((userSnapshot, index) => {
  const user = userSnapshot.data();
  const userID = user.userID;
  const docRef = db.doc(`users/${userID}/inbox/${notificationID}`);
  currentBatch.set(docRef, notificationData);

  operationCount++;
  // 达到Batch上限或者处理到最后一个文档时,保存当前Batch并重置
  if (operationCount === maxBatchOperations || index === userDocs.length - 1) {
    batches.push(currentBatch);
    currentBatch = db.batch();
    operationCount = 0;
  }
});

// 每20个Batch(对应10000次写入)为一组,组间间隔1.1秒
const batchesPerSecond = 20;
for (let i = 0; i < batches.length; i += batchesPerSecond) {
  const currentBatchGroup = batches.slice(i, i + batchesPerSecond);
  // 并行执行当前组的所有Batch
  await Promise.all(currentBatchGroup.map(batch => batch.commit()));

  // 如果不是最后一组,等待1.1秒
  if (i + batchesPerSecond < batches.length) {
    await new Promise(resolve => setTimeout(resolve, 1100));
  }
}

return "所有通知已发送完成";

额外提醒

  • 云函数超时:处理25000个用户大概需要3-4秒(2批9000+1批7000,加两次延迟),远低于云函数默认的90秒超时上限,不用担心超时问题。
  • 错误处理:如果需要更稳健,可以在每批处理时加入try/catch,避免单个失败导致整个任务中断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 19:22:40