DynamoDB добавление в несколько списков атомарно - PullRequest
0 голосов
/ 21 ноября 2018

У меня есть запись с двумя списками.Несколько сервисов добавляются в эти списки одновременно, каждый сервис обновляет ровно один из этих списков.

это мой код для создания UpdateItemSpec

private UpdateItemSpec updateList1(List<String> values) {
        return new UpdateItemSpec()
                .withPrimaryKey("recordKey", "key")
                .withUpdateExpression("SET list1 = list_append(if_not_exists(list1, :initialVal), :val)")
                .withValueMap(new ValueMap().withList(":val", values)
                        .withList(":initialVal", new ArrayList<>()))
                .withReturnValues(ReturnValue.ALL_NEW);
    }

    private UpdateItemSpec updateList2(List<String> values) {
        return new UpdateItemSpec()
                .withPrimaryKey("recordKey", "key")
                .withUpdateExpression("SET list2 = list_append(if_not_exists(list2, :initialVal), :val)")
                .withValueMap(new ValueMap().withList(":val", values)
                        .withList(":initialVal", new ArrayList<>()))
                .withReturnValues(ReturnValue.ALL_NEW);
    }

Учитывая, что обновления должны получить менядо состояния, в котором списки равны (я не знаю, сколько нужно итераций), моя цель - проверить, равны ли списки после каждого update (используя элемент, возвращенный из update).Нужно ли что-то делать, чтобы убедиться, что updates является атомарным в записях, и я не пропущу итерацию, в которой списки стали равными?

Другими словами, update полностью блокирует запись или просто блокирует текущее обновленное поле?

1 Ответ

0 голосов
/ 21 ноября 2018

Обновление для одного элемента является атомарным, поэтому, если вы используете ReturnValues.ALL_NEW, вы сможете увидеть полное состояние элемента, и вы не пропустите его, если списки равны.(См. Документацию update .)

Даже если вы увидите, что списки равны, возможно, что списки не будут равны к тому времени, когда вы сможете реагировать на них.быть равнымЕсли вы хотите убедиться, что список остается равным до тех пор, пока вы не сможете реагировать, вам понадобится выражение условия для предотвращения дальнейших обновлений или решение распределенной блокировки.

Редактировать (2018-11-22)

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

Давайте начнем со следующегодопущения:

  1. A условная запись полностью успешна для элемента, если условие истинно.
  2. Условная запись отклоняется, если условие ложно.
  3. Условные записи могут использоваться для Оптимистическая блокировка с номером версии .
  4. Запись не обновляет все атрибуты атомарно.

Предположим, что мы имеемэлемент с атрибутами hashkey, version и data.Допустим, что hashkey=123, data = "Foo" и version = 1.

Предположим также, что есть два запроса (запрос A и запрос B), которые поступают почти одновременно, и оба используют оптимистическийблокировка и оба пытаются установить новое значение для data.

Вот возможная последовательность событий

  • Запрос A - Проверьте условие version==1
  • Запрос B - Проверьте условие version==1
  • Запрос A - data = "Bar"
  • Запрос B - data = "Bag"
  • Запрос A - version=version+1
  • Запрос B - version=version+1

Конечное состояние элемента:

hashkey=123
version=3
data="Bag"

Это состояние не должно возникать из-за оптимистической блокировки.

Если вы используете эту стратегию, то записи вашей базы данных будут защищены от перезаписи записями других пользователей - и наоборот.

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

Однако это только показывает, что, по крайней мере, некоторые атрибуты должны обновляться атомарно, а не то, что все они есть.Ну, здесь есть две возможные реализации.(1) DynamoDB определяет, какие атрибуты присутствуют в выражении условия (от 0 до всех их) и обновляет только те, которые атомарно.(2) DynamoDB обновляет все атрибуты для элемента атомарно.Но рассмотрим этот пример, в котором атрибуты, отсутствующие в выражении ConditionExpression, влияют на правильность обновления.

Предположим, что у нашего элемента есть еще 1 атрибут: canEdit, что изначально истинно.На этот раз Запрос A устанавливает canEdit=false, а Запрос B устанавливает values = list_append(values, "Bar").

Если все атрибуты не обновляются атомарно, вот возможная последовательность событий:

  • Запрос A- Проверить условие version==1 AND data=="Foo"
  • Запрос A - version = version+1
  • Запрос A - `data =" Foo "
  • Запрос B - Проверить условие canEdit==true
  • Запрос B - version = version+1
  • Запрос B - canEdit = true
  • Запрос A - canEdit = false
  • Запрос B - data = "Bar"

В обоих случаях условияЗначение true при первоначальной оценке, и в обоих случаях записанный запрос был переопределен другим запросом.DynamoDB не допустит успешного выполнения обоих этих условных обновлений, поэтому DynamoDB должен обновлять все атрибуты элемента атомарно, потому что это единственный способ гарантировать, что A или B потерпят неудачу с условием исключения ConditionCheckException.

Если мои рассужденияявляется правильным, то для того, чтобы 1-3 было истинным, 4 должно быть ложным, и все атрибуты в одном элементе обновляются атомарно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...