我们正在使用DynamoDB来计算用户操作,并且必须插入或更新项目,具体取决于它已存在的内容。代码还必须更新计数器。现在我们通过两个步骤完成此任务:
using (var client = AWSClientFactory.CreateAmazonDynamoDBClient(RegionEndpoint.USEast1))
{
var table = Table.LoadTable(client, TableName);
var item = await table.GetItemAsync(id);
if (item == null)
{
// row not exists -> insert & return 1
var document = new Document();
document["Id"] = id;
document["Counter"] = 1;
await table.PutItemAsync(document);
return 1;
}
// row exists -> increment counter & update
var counter = item["Counter"].AsInt();
item["Counter"] = counter + 1;
await table.UpdateItemAsync(item);
return counter + 1;
}
代码的问题在于它增加了延迟时间&服务器负载。我希望通过一次操作来完成这项工作。我认为这应该可以使用conditional expressions,但我无法弄清楚如何使用.NET SDK来实现这一点。
答案 0 :(得分:1)
要小心自己递增计数器,因为如果你的应用的多个实例可以递增计数器,你可能会遇到竞争条件。而是使用DynamoDB Atomic Counters。例如,我的ruby代码使用以下(较旧的)递增计数器的方式调用UpdateItem API:
{"counter" => {value: {n: "1"}, action: "ADD"}}
更新的方法是使用我尚未实施的Update Expression。此外,如果计数器/项目不存在,它将假定值为0并将计数器增加到1.
答案 1 :(得分:0)
您的代码中存在竞争条件。 2个不同的工人可能同时创建该项目。
您尝试做的推荐模式是:
因此,而不是3个操作(获取,放置,更新) - 也有竞争条件 - 在这种情况下,您将只有2个操作(以及正确的行为)
希望这会有所帮助。