Lambda函数调用DynamoDB Update API时数值重复递增问题排查
问题:Lambda中DynamoDB原子计数器递增两次,本地执行正常
我使用Lambda函数通过DynamoDB的.update API实现原子计数器,对表中数值进行递增操作,但每次执行都会导致数值被递增两次。例如表中初始值为2,递增值设为1,执行后数值变为4而非预期的3。而移除handler函数后,相同逻辑在VSCode中通过JS SDK执行却能正常工作,请问问题出在哪里?
Lambda函数代码
'use strict'; const AWS = require("aws-sdk"); AWS.config.update({ region: "me-central-1" }); const docClient = new AWS.DynamoDB.DocumentClient(); exports.handler = async (event) => { await docClient.update( { TableName: "visitor-counter-table", Key: { "visitor-counter": "counter", }, UpdateExpression: "set #num = #num + :incr", ExpressionAttributeNames: { "#num": "number", }, ExpressionAttributeValues: { ":incr": 1, }, }, (err, data) => { err ? console.log(err) : console.log(data); } ).promise(); return {"statusCode": 200, "body": "number added to DDB Success"} };
VSCode本地执行代码
const AWS = require("aws-sdk"); AWS.config.update({ region: "me-central-1" }); const docClient = new AWS.DynamoDB.DocumentClient(); docClient.update( { TableName: "visitor-counter-tbl", Key: { "visitor-counter": "counter", }, UpdateExpression: "set #num = #num + :incr", ExpressionAttributeNames: { "#num": "number", }, ExpressionAttributeValues: { ":incr": 1, }, }, (err, data) => { err ? console.log(err) : console.log(data); } );
解决方法
问题出在你同时使用了回调函数和.promise()调用DynamoDB的update方法。AWS SDK的API设计中,如果同时传入回调函数并调用.promise(),会触发两次update请求:一次以回调模式执行,一次以Promise模式执行,直接导致数值被递增两次。
本地代码里只传入了回调函数,没有调用.promise(),所以只会执行一次update操作,结果符合预期。
修正后的Lambda代码只需二选一:要么用Promise/await(推荐),要么用回调,不要混用。以下是推荐的Promise/await写法:
'use strict'; const AWS = require("aws-sdk"); AWS.config.update({ region: "me-central-1" }); const docClient = new AWS.DynamoDB.DocumentClient(); exports.handler = async (event) => { try { // 只使用promise方式,去掉回调函数 const data = await docClient.update({ TableName: "visitor-counter-table", Key: { "visitor-counter": "counter", }, UpdateExpression: "set #num = #num + :incr", ExpressionAttributeNames: { "#num": "number", }, ExpressionAttributeValues: { ":incr": 1, }, }).promise(); console.log(data); } catch (err) { console.error(err); } return {"statusCode": 200, "body": "number added to DDB Success"} };
内容的提问来源于stack exchange,提问作者b_a9f
相关产品推荐
相关产品推荐

