文档数据库删除大量记录

编程语言 2026-07-09

有个小问题:我需要从AWS DocumentDB集群删除大约100万条记录。要求是在删除每条文档的同时,也向EventBridge发送一个指示该文档已被删除的事件。

挑战在于,为了发送事件,我必须在删除文档之前读取它们。这一过程会造成高CPU使用率,最终因为资源耗尽而重启我的ECS任务。

目前我把所有记录都读进内存,这会重启我的ECS任务。我在考虑一种做法:读取记录的id,将它们存入SQS,然后逐条读取并由Lambda将它们删除。不确定这是否是正确的做法,是否有人遇到过类似的问题?

解决方案

与一次性将所有ID读入内存相比,我建议使用分页游标,分批将数据喂入SQS:

ECS Task (coordinator)
-> cursor through DocumentDB in pages of ~100-500 docs
-> write batches of IDs to SQS (up to 10 messages per SendMessageBatch)
-> Lambda consumes SQS, reads full doc then sends EventBridge event then deletes doc
  1. Cursor pagination in the coordinator example
const batchSize = 500;
let lastId = null;

while (true) {
  const query = lastId ? { _id: { $gt: lastId } } : {};

  const batch = await collection
    .find(query, { projection: { _id: 1 } })
    .sort({ _id: 1 })
    .limit(batchSize)
    .toArray();

  if (batch.length === 0) break;

  // Send to SQS in groups of 10 (SDK batch limit)
  await sendToSQSInChunks(batch.map(doc => doc._id));

  lastId = batch[batch.length - 1]._id;

  await sleep(100);
}
  1. Lambda consumer — read, event and delete
export const handler = async (event) => {
  for (const record of event.Records) {
    const { docId } = JSON.parse(record.body);

    // 1. Read full document (needed for EventBridge payload)
    const doc = await collection.findOne({ _id: docId });
    if (!doc) continue; // already deleted

    // 2. Send EventBridge event first
    await eventBridge.putEvents({
      Entries: [{
        Source: 'my-app.documents',
        DetailType: 'DocumentDeleted',
        Detail: JSON.stringify(doc),
        EventBusName: 'your-bus-name',
      }]
    }).promise();

    // 3. Delete only after event is confirmed sent
    await collection.deleteOne({ _id: docId });
  }
};

顺序很重要:在删除之前发送事件。如果删除成功但事件失败,你就失去了发出事件的能力。如果事件成功但删除失败,SQS将会重试,findOne也会再次发出(如果你的消费者能够处理重复,则具有幂等性)。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章