文档数据库删除大量记录
有个小问题:我需要从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
- 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);
}
- 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导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。