2016-02-27 5 views
3

Я пытаюсь понять, является ли Оптимистическая блокировка DynamoDB правильной вещью для моего варианта использования, или я должен делать что-то еще.Правильный способ использования Оптимистической блокировки DynamoDB

Я пытаюсь сделать следующее в своем методе Java.

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

Я хочу обновить один и тот же элемент на основе некоторого состояния. Я создал атрибут версии, так что оптимистическая блокировка работает, и когда у меня появляется несколько запросов, только один запрос получает и обновляет данные.

Я пытаюсь понять следующее:

  1. Что происходит, когда другой поток пытается обновить значение, но и номер версии изменился, я не мог найти какой-либо документации о том, что исключение будет бросили?

  2. Должен ли я использовать синхронизированную функцию для этого? Принимая во внимание несколько запросов? Но для меня это похоже на то, что он побеждает цель оптимистической блокировки, так как мне все равно, какой запрос получает доступ в первую очередь.

  3. Есть ли альтернативное решение этой проблемы?

Я через следующую документацию: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBMapper.OptimisticLocking.html

ответ

3
  1. Что происходит, когда другой поток пытается обновить значение, кроме версии идентификатор изменился, я не мог найти любая документация по поводу того, что будет выбрано исключение ?

Оказывается бросить ConditionalCheckFailedException, если версия ID изменилась.

  1. Должен ли я использовать синхронизированную функцию для этого? Принимая во внимание , поступит много запросов? Но мне кажется, что это поражает цель оптимистической блокировки, так как мне все равно, какой запрос получает доступ.

Вы правильно, с помощью функции синхронизированной бы поражение цели оптимистической блокировки. Вам не нужны оба. Оптимистическая блокировка работает в распределенной среде, где обновления могут не генерироваться одними и теми же серверами.

  1. Есть ли альтернативное решение этой проблемы?

Вы можете использовать DynamoDB API низкого уровня и условное обновление. Я думаю, что это то, что использует Optimistic Locking. Если вы используете язык, отличный от Java или .Net, вам придется использовать низкоуровневый API. Поскольку вы используете Java и уже работаете с API высокого уровня, я бы придерживался этого.

+0

Hi Mark. Спасибо за это. Не могли бы вы сослаться на источник для исключения? Я проверил Javadoc здесь goo.gl/ZRAzOQ, но ничего не нашел. Эта страница http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ErrorHandling.html#APIError упоминает что-то об этом, но ей не хватает деталей. – abeer

+0

Как я могу гарантировать, что сбой произошел из-за измененной версии, а не какого-то другого условия? Вызывает ли 'ConditionalCheckFailedException' какой тип отказа? Или есть другие способы узнать это? – Nawaz

0

Если вам нужно, чтобы гарантировать, что были применены все многочисленные запросы (из разных потоков/серверов), можно использовать следующую реализацию оптимистической блокировки:

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..."); 
     } 
    } 
} 

Вот если элемент уже был обновлен другим запрос , мы получим ConditionalCheckFailedException и попробуем еще раз, пока не будут применены изменения.

ConditionalCheckFailedException - это исключение генерируется, когда ожидаемое значение не соответствует найденному в системе (базе данных). Это исключение будет выбрано:

  • если вы используете оптимистичную блокировку с помощью @DynamoDBVersionAttribute, а значение версии на сервере отличается от значения на стороне клиента;
  • если вы укажете свои собственные условные ограничения при сохранении/удалении данных с помощью dynamoDBMapper с помощью DynamoDBSaveExpression/DynamoDBDeleteExpression, и эти ограничения не удались.

Что касается вопроса @Nawaz, если вы не указали свои собственные условные ограничения (используя DynamoDBSaveExpression и DynamoDBDeleteExpression), это исключение связано с измененной версией. Если вы поймаете ConditionalCheckFailedException, вы получите следующую информацию:

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