使用AWS Lambda批量写入DynamoDB时数据丢失,无报错无未处理项
问题分析与可能原因
针对你遇到的Lambda批量写入DynamoDB后数据量不符的问题,结合代码和日志信息,以下是几个核心排查方向:
1. 数据统计时未处理DynamoDB查询分页限制
DynamoDB的Scan/Query操作单次返回结果上限为1MB数据或1000条记录(取较小值)。如果统计数据时只执行了一次查询,未通过LastEvaluatedKey进行分页遍历,你看到的14000条很可能只是单次查询的部分结果,实际20000条数据已全部写入。
验证方式:执行查询时循环处理LastEvaluatedKey,直到结果中无该字段,再汇总所有分页的记录数。
2. 代码中表名引用不一致
你的代码存在两处表名引用:
- 批量写入逻辑使用硬编码的
"myTable"作为表名 - 最后一批数据的写入判断使用
CardManager.instance().getTableName()获取表名
如果这两个表名不统一,最后一批未凑满24条的数据会被直接忽略,无法写入目标表。虽然该问题只会导致少量数据丢失,但仍需确认表名是否完全一致。
修复建议:统一使用动态获取的表名,避免硬编码:
async function writeOnDynamoDB(items: any, ruleId: string) { const dynamoDB = new AWS.DynamoDB.DocumentClient(); const tableName = CardManager.instance().getTableName(); // 统一获取表名 const batchWriteParams: AWS.DynamoDB.DocumentClient.BatchWriteItemInput = { RequestItems: { [tableName]: [], }, }; console.log('Start inserting rows') for (let i = 0; i < items.length; i++) { let item = items[i]; item.id = ruleId const putRequest: AWS.DynamoDB.DocumentClient.WriteRequest = { PutRequest: { Item: item, }, }; batchWriteParams.RequestItems[tableName].push(putRequest); if (i > 0 && i % 24 === 0) { console.log("Insert chunck", i,) const result = await dynamoDB.batchWrite(batchWriteParams).promise(); console.log('Result',result) batchWriteParams.RequestItems[tableName] = []; } } if (batchWriteParams.RequestItems[tableName].length > 0) { await dynamoDB.batchWrite(batchWriteParams).promise(); } }
3. 同一分区键写入的隐性流量控制
尽管表使用按需模式,但DynamoDB对单个分区键的写入有初始吞吐量限制(默认每秒1000次写入)。短时间内向同一分区键写入20000条数据,可能触发流量控制,部分写入操作未返回UnprocessedItems但实际未成功落地。
修复建议:添加UnprocessedItems重试逻辑(带指数退避),确保所有请求被处理:
async function batchWriteWithRetry(params: AWS.DynamoDB.DocumentClient.BatchWriteItemInput) { let result = await dynamoDB.batchWrite(params).promise(); // 循环重试未处理的请求 while (Object.keys(result.UnprocessedItems).length > 0) { await new Promise(resolve => setTimeout(resolve, 200)); // 指数退避可优化 result = await dynamoDB.batchWrite({ RequestItems: result.UnprocessedItems }).promise(); } } // 替换原batchWrite调用 await batchWriteWithRetry(batchWriteParams);
4. 输入数据存在隐性重复(覆盖写入)
即使你确认partitionKey+sortkey组合唯一,仍可能存在代码逻辑导致键组合重复:
item.id = ruleId修改了分区键或排序键,破坏了原本的唯一性items数组中存在引用同一对象的元素,修改id后多个item的键组合一致,后续PutRequest覆盖了之前的写入
验证方式:写入前打印所有item的partitionKey和sortkey值,确认组合唯一;或写入后查询所有数据的键组合,检查是否存在重复。
内容的提问来源于stack exchange,提问作者Mikfaina
相关产品推荐
相关产品推荐

