我们使用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;
}
代码的问题在于它增加了延迟时间&服务器负载。我更愿意做一次手术。我认为条件表达式应该可以做到这一点,但我不知道如何使用.NET SDK来实现这一点。
要小心自己递增计数器,因为如果应用程序的多个实例可以递增计数器,则可能会出现竞争条件。而是使用DynamoDB原子计数器。例如,我的ruby代码使用以下(较旧的(递增计数器的方法调用UpdateItem API:
{"counter" => {value: {n: "1"}, action: "ADD"}}
更新的方法是使用更新表达式,我还没有实现它。此外,如果计数器/项还不存在,它将假定值为0,并将计数器递增到1。
您的代码中有一个竞赛条件。两个不同的工作人员可能同时创建项目。
推荐的模式是:
- 为项创建"如果不存在"操作
- 原子计数器更新"计数">
因此,在这种情况下,您将只有2个操作(和正确的行为(,而不是3个操作(获取、放置、更新(-也有竞争条件
希望这能有所帮助。