java 使用 DynamoDB 乐观锁的正确方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35672713/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 00:26:37  来源:igfitidea点击:

Correct way to use DynamoDB Optimistic Locking

javaamazon-web-servicesamazon-dynamodb

提问by abeer

I'm trying to understand if DynamoDB Optimistic Locking is the correct thing for my use case or should I be doing something else.

我试图了解 DynamoDB Optimistic Locking 是否适合我的用例,或者我应该做其他事情。

I'm trying to do the following in my Java method.

我正在尝试在我的 Java 方法中执行以下操作。

function updateItem(String key) {
    Item item = mapper.load(Item.class, key);
    if (some condition) {
        item.setValue(item.getValue() + 1);
        mapper.save(item);
    }
 }

I want to update the same item based on some condition succeeding. I've created a version attribute, so that Optimistic locking works and when I have multiple requests coming in, only one request gets and updates the data.

我想根据成功的某些条件更新相同的项目。我创建了一个版本属性,以便乐观锁定工作,当我有多个请求进入时,只有一个请求获取和更新数据。

I'm trying to understand the following:

我试图理解以下内容:

  1. What happens when some other thread tries to update the value but the version id has changed, I couldn't find any documentation on what exception will be thrown?

  2. Should I be using a synchronized function for this? Considering multiple requests will be coming in? But, to me this seems like it defeats the purpose of optimistic locking, since I don't care which request gets access first.

  3. Is there an alternate solution to this problem?

  1. 当其他线程尝试更新该值但版本 id 已更改时会发生什么,我找不到有关将抛出什么异常的任何文档?

  2. 我应该为此使用同步函数吗?考虑到多个请求会进来?但是,对我来说,这似乎违背了乐观锁定的目的,因为我不在乎哪个请求首先获得访问权限。

  3. 这个问题有替代解决方案吗?

I've been through the following documentation: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBMapper.OptimisticLocking.html

我已经阅读了以下文档:http: //docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBMapper.OptimisticLocking.html

回答by Mark B

  1. What happens when some other thread tries to update the value but the version id has changed, I couldn't find any documentation on what exception will be thrown?
  1. 当其他线程尝试更新该值但版本 id 已更改时会发生什么,我找不到有关将抛出什么异常的任何文档?

It appears to throw a ConditionalCheckFailedException if the version ID has changed.

如果版本 ID 已更改,它似乎会抛出 ConditionalCheckFailedException。

  1. Should I be using a synchronized function for this? Considering multiple requests will be coming in? But, to me this seems like it defeats the purpose of optimistic locking, since I don't care which request gets access first.
  1. 我应该为此使用同步函数吗?考虑到多个请求会进来?但是,对我来说,这似乎违背了乐观锁定的目的,因为我不在乎哪个请求首先获得访问权限。

You are correct, using a synchronized function would defeat the purpose of optimistic locking. You don't need both. And optimistic locking works in a distributed environment where updates may not be generated by the same servers.

你是对的,使用同步函数会破坏乐观锁定的目的。你不需要两者。乐观锁定适用于分布式环境,其中更新可能不会由相同的服务器生成。

  1. Is there an alternate solution to this problem?
  1. 这个问题有替代解决方案吗?

You could use the low-level DynamoDB API and Conditional Updates. I think that's what the Optimistic Locking is using underneath. If you were using a language other than Java or .Net you would have to use the low-level API. Since you are using Java and already working with the high-level API I would stick with that.

您可以使用低级 DynamoDB API 和条件更新。我认为这就是乐观锁定在下面使用的内容。如果您使用 Java 或 .Net 以外的语言,则必须使用低级 API。由于您正在使用 Java 并且已经在使用高级 API,因此我会坚持下去。

回答by Vasiliy Sarzhynskyi

If you need to guarantee that all multiple requests (from different threads / servers) were applied, you could use the following implementation of optimistic locking:

如果您需要保证所有多个请求(来自不同线程/服务器)都被应用,您可以使用以下乐观锁定的实现:

public void updateItem(String key) {
    while (true) {
        try {
            Item item = dynamoDBMapper.load(Item.class, key);
            if (some condition) {
                item.setValue(item.getValue() + 1);
                dynamoDBMapper.save(item);
            }
            break;
        } catch (ConditionalCheckFailedException e) {
            System.out.println("ConditionalCheckFailedException. Retrying again...");
        }
    }
}

Here if item has already been updated by another request, we will receive ConditionalCheckFailedException and trying one more time until changes will be applied.

在这里,如果项目已被另一个请求更新,我们将收到 ConditionalCheckFailedException 并再试一次,直到应用更改。

ConditionalCheckFailedException- this exception is thrown when an expected value does not match what was found in the system (database). This exception will be thrown:

ConditionalCheckFailedException- 当预期值与在系统(数据库)中找到的值不匹配时抛出此异常。将抛出此异常:

  • if you use optimistic locking with @DynamoDBVersionAttribute, and version value on the server is different from value on the client side;
  • if you specify your own conditional constraints while saving / deleting data using dynamoDBMapper with DynamoDBSaveExpression / DynamoDBDeleteExpression and these constraints are failed.
  • 如果您对@DynamoDBVersionAttribute 使用乐观锁定,并且服务器上的版本值与客户端的值不同;
  • 如果您在使用 dynamoDBMapper 和 DynamoDBSaveExpression / DynamoDBDeleteExpression 保存/删除数据时指定自己的条件约束,并且这些约束失败。

Regarding @Nawaz question, if you haven't specified your own conditional constraints (using DynamoDBSaveExpression and DynamoDBDeleteExpression), this exception is due to changed version. If you catch ConditionalCheckFailedException, you will have the following information:

关于@Nawaz 问题,如果您尚未指定自己的条件约束(使用 DynamoDBSaveExpression 和 DynamoDBDeleteExpression),则此异常是由于版本更改所致。如果您捕获 ConditionalCheckFailedException,您将获得以下信息:

requestId = …
errorCode = ConditionalCheckFailedException
errorType = {AmazonServiceException$ErrorType} "Client"
errorMessage = The conditional request failed
statusCode = 400
serviceName = AmazonDynamoDBv2