Можно ли атомарно увеличивать атрибут таблицы как одну из нескольких операций в функции транзакций DynamoDB? - PullRequest
0 голосов
/ 27 апреля 2020

У нашей команды есть таблица DDB, которая содержит элементы с атрибутом 'state', обозначающим различные состояния жизненного цикла. У нас есть другая таблица, которая отслеживает количество этих элементов по состоянию (ключ разделения - это идентификатор типа контейнера, по которому сгруппированы элементы набора, ключ сортировки - это состояние). В настоящее время мы используем лямбду, чтобы поддерживать счет в syn c, инициируемом потоком ddb в таблице, содержащей элементы, но у нас были некоторые проблемы с этим (задержка, идемпотентность) и мы рассматриваем использование транзакций DynamoDB как способ обновлять таблицу счетчиков синхронно всякий раз, когда мы меняем состояние элемента.

Мне было интересно, есть ли способ сделать атоми c, инкрементальное добавление с использованием AttributeValueUpdate + 'AttributeAction.ADD', например в этом примере но в пределах транзакции DynamoDB, чтобы обновление состояния элемента и увеличение счетчика были операцией ACID, "все или ничего"? Подход в примере использует UpdateItemRequest с AttributeValueUpdate, хотя кажется, что транзакции могут использовать только объект обновления , и я не смог найти способ использовать AttributeValueUpdate с этим объектом. здесь

Из моего понимания Транзакций нет никакого упорядочения для независимых операций, поэтому никакая операция не может зависеть от вывода другой (я не могу прочитать значение, затем добавить к нему в той же транзакции), и если я сначала прочитайте значение, оно может быть изменено ко времени совершения транзакции. Мне не удалось найти какой-либо другой пример увеличения значения внутри транзакции DynamoDB, в надежде, что кто-нибудь скажет мне, возможно ли это.

1 Ответ

1 голос
/ 28 апреля 2020

Это определенно возможно, у вас просто нет доступа к плавному API, который UpdateItemRequest использует для построения выражения обновления (через AttributeValueUpdate). Вместо этого вы должны написать выражение обновления вручную.

В приведенном вами примере следующее:

UpdateItemRequest updateRequest =
    new UpdateItemRequest().withTableName("local-content")
        .withKey(key)
        .addAttributeUpdatesEntry("views", new AttributeValueUpdate()
            .withValue(new AttributeValue().withN("" + delta))
            .withAction(AttributeAction.ADD));

эквивалентно примерно так:

// Create a map of expression attribute values with the amount to increment by
Map<String, AttributeValue> values = new HashMap<String, AttributeValue>();
values.put(":one", new AttributeValue().withN("1"));

Update update =
    new Update().withTableName("local-content")
        .withKey(key)
        .withExpressionAttributeValues(values)
        .withUpdateExpression("ADD views :one");

Имея это в виду, имейте в виду, что транзакции DynamoDB значительно дороже, чем нетранзакционные операции, и то, что вы пытаетесь сделать, вероятно, распадется при высокой пропускной способности, так как счетчики станут горячими клавишами.

...