ConditionalCheckFailedException出现在DynamoDB乐观锁定的第一项中

问题描述 投票:0回答:1

我尝试在更新DynamoDB中的记录之前设置乐观版本检查。但是当没有哈希键存在时,我一直从保存第一项中获取ConditionalCheckFailedException

有人可以告诉我我的代码有什么问题吗?

这是我的代码

final DynamoDBMapperConfig.Builder builder = new DynamoDBMapperConfig.Builder();
builder.setConsistentReads(DynamoDBMapperConfig.ConsistentReads.CONSISTENT);
builder.setTableNameOverride(new DynamoDBMapperConfig.TableNameOverride(tableName));
DynamoDBMapperConfig mapperConfig = builder.build();
this.dynamoDBMapper = new DynamoDBMapper(amazonDynamoDB, mapperConfig);
@Data
@DynamoDBTable(tableName = "OVERRIDE_AT_RUNTIME")
public class ItemRecord
{
    public static final String CONTENT_ID = "content_id";
    public static final String ACTION_COUNT = "action_count";
    private static final String VERSION = "version";

    @DynamoDBHashKey(attributeName = CONTENT_ID)
    private String contentId;
    @DynamoDBAttribute(attributeName = ACTION_COUNT)
    private int actionCount;
    @DynamoDBVersionAttribute(attributeName = VERSION)
    private long version;

    public TitleMatchProgressRecord() {}

    public TitleMatchProgressRecord(final String contentId)
    {
        this.contentId = contentId;
        this.actionCount = 0;
    }

    @DynamoDBIgnore
    public void incrementActionCount()
    {
        actionCount++;
    }
}
try {
    ItemRecord itemRecord = loadRecord(contentId);
    if (itemRecord == null) { // first item
        itemRecord = new ItemRecord(contentId);
        itemRecord.incrementActionCount();
        DynamoDBSaveExpression saveExpression = new DynamoDBSaveExpression();
        final Map<String, ExpectedAttributeValue> expectedAttributes = new HashMap<>();
        expectedAttributes.put(ItemRecord.CONTENT_ID, new ExpectedAttributeValue(false));
        saveExpression.setExpected(expectedAttributes);

        dynamoDBMapper.save(itemRecord, saveExpression);

    } else {
        itemRecord.incrementActionCount();
        itemRecord.resetLastModifiedAt();
        dynamoDBMapper.save(itemRecord);
    }
} catch (ConditionalCheckFailedException e) {
    // retry
}

错误跟踪:

   [testng] com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException: The conditional request failed (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ConditionalCheckFailedException; Request ID: UV4V9BSIE78ETRQC9LG4BOB23; Proxy: null)
   [testng]     at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleErrorResponse(AmazonHttpClient.java:1811)
   [testng]     at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleServiceErrorResponse(AmazonHttpClient.java:1395)
   [testng]     at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeOneRequest(AmazonHttpClient.java:1371)
   [testng]     at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeHelper(AmazonHttpClient.java:1145)
   [testng]     at com.amazonaws.http.AmazonHttpClient$RequestExecutor.doExecute(AmazonHttpClient.java:802)
   [testng]     at com.amazonaws.http.AmazonHttpClient$RequestExecutor.executeWithTimer(AmazonHttpClient.java:770)
   [testng]     at com.amazonaws.http.AmazonHttpClient$RequestExecutor.execute(AmazonHttpClient.java:744)
   [testng]     at com.amazonaws.http.AmazonHttpClient$RequestExecutor.access$500(AmazonHttpClient.java:704)
   [testng]     at com.amazonaws.http.AmazonHttpClient$RequestExecutionBuilderImpl.execute(AmazonHttpClient.java:686)
   [testng]     at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:550)
   [testng]     at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:530)
   [testng]     at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.doInvoke(AmazonDynamoDBClient.java:5110)
   [testng]     at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.invoke(AmazonDynamoDBClient.java:5077)
   [testng]     at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.executeUpdateItem(AmazonDynamoDBClient.java:4696)
   [testng]     at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient.updateItem(AmazonDynamoDBClient.java:4662)
   [testng]     at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper$SaveObjectHandler.doUpdateItem(DynamoDBMapper.java:871)
   [testng]     at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper$2.executeLowLevelRequest(DynamoDBMapper.java:611)
   [testng]     at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper$SaveObjectHandler.execute(DynamoDBMapper.java:750)
   [testng]     at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper.save(DynamoDBMapper.java:640)
   [testng]     at com.amazonaws.services.dynamodbv2.datamodeling.AbstractDynamoDBMapper.save(AbstractDynamoDBMapper.java:123)
amazon-web-services amazon-dynamodb optimistic-locking
1个回答
0
投票

要在DynamoDB中进行“乐观锁定”,您需要在项目上保留一个版本属性-称为“动作计数”。如果有可能该项目尚不存在,并且需要首次创建-您必须明确处理这种情况。您不能仅仅假设项目始终存在并且具有先前的操作计数...例如,您可以执行以下操作:

  1. 读取项目(您可以通过更便宜的“最终一致性”进行读取)。该项目以前可能不存在-很好。

  2. 根据您所阅读的内容,创建该项目的新版本。如果该项目存在,则将“动作计数”加1,否则将动作计数设置为0。

  3. 使用条件表达式执行写入。如果该项目先前存在,则该条件应要求操作计数仍等于其读取(预递增)值。如果该项目以前不存在,则条件应该是该项目不存在。

  4. 如果条件更新在失败的条件下失败,请转到1重试。

[请注意,如果两个并发写入尝试创建一个新项目,一个将成功创建它(操作计数为0,而另一个则需要重试并实际更新该项目(最终导致操作计数为1)。] >

© www.soinside.com 2019 - 2024. All rights reserved.