Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct way to use DynamoDB Optimistic Locking

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

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

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?

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

like image 365
abeer Avatar asked Feb 27 '16 17:02

abeer


People also ask

What is optimistic locking DynamoDB?

Optimistic locking is a strategy to ensure that the client-side item that you are updating (or deleting) is the same as the item in Amazon DynamoDB. If you use this strategy, your database writes are protected from being overwritten by the writes of others, and vice versa.

How does DynamoDB lock work?

The DynamoDB Lock Client implements a protocol allowing similar applications to take advisory locks on any part of your problem domain, big or small. This protocol ensures your players “stay in possession of the ball” for a certain period of time. For a new lock, the lock client stores a lock item in the lock table.

What is optimistic and pessimistic locking?

Optimistic locking , where a record is locked only when changes are committed to the database. Pessimistic locking , where a record is locked while it is edited.

Can glue read from DynamoDB?

The DynamoDB export feature allows exporting table data to Amazon S3 across AWS accounts and AWS Regions. After the data is uploaded to Amazon S3, AWS Glue can read this data and write it to the target table.


2 Answers

  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?

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

  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.

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?

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.

like image 172
Mark B Avatar answered Sep 28 '22 05:09

Mark B


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 - this exception is thrown when an expected value does not match what was found in the system (database). This exception will be thrown:

  • 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.

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:

requestId = …
errorCode = ConditionalCheckFailedException
errorType = {AmazonServiceException$ErrorType} "Client"
errorMessage = The conditional request failed
statusCode = 400
serviceName = AmazonDynamoDBv2
like image 44
Vasyl Sarzhynskyi Avatar answered Sep 28 '22 03:09

Vasyl Sarzhynskyi