DynamoDB атомарно обновляет счетчик

Новичок DynamoDB, заинтересованный в изучении баз данных NoSQL.

У меня есть сценарий, в котором у меня есть таблица с ключом раздела userId, ключом сортировки времени и числовым дескриптором. Дескриптор представляет собой последовательный счетчик, который увеличивается на 1.

Вот пример таблицы:

userId, time, handle
0     , 123 , 1
0     , 456 , 2
1     , 123 , 1
1     , 234 , 2
0     , 789 , 3
1     , 345 , 3

для данного идентификатора пользователя дескрипторы не могут иметь дубликатов

Что я хочу сделать, так это добавить новую запись для userId 0, для времени 891 и иметь дескриптор на 1 больше, чем последняя записанная запись для userId 0, которая будет предпоследней строкой в ​​​​базе данных, то есть 3 + 1 = 4.

Наивный способ — запросить в базе данных userId со значением 0, отсортировав по последней метке времени (если это вообще возможно), чтобы получить дескриптор (3). Это первая просьба. Затем вы должны создать запрос put_item в базе данных, который добавляет 1 к дескриптору (3 + 1 = 4) и создает новую запись.

Здесь явно присутствует состояние гонки, когда между запросом чтения и созданием запроса put_item другая лямбда/API/конечная точка могла зафиксировать новую запись в базе данных с тем же дескриптором (4), например. (1, 888, 4). Когда я фиксирую свою исходную запись (0, 891, 4), дескриптор равен 4, тогда как сейчас он должен быть 5.

Можно ли выполнить эту операцию чтения и записи в одной транзакции (возможно, у меня неправильное мышление).

Дайте мне знать, если мой вопрос не ясен.


person Prof    schedule 19.09.2018    source источник


Ответы (2)


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

person cementblocks    schedule 20.09.2018

То, что вы пытаетесь сделать: «назначить монотонно возрастающее числовое значение в качестве уникального идентификатора» — это анти-шаблон с распределенными базами данных (noSql или иначе)

Найдите минутку и подумайте о проблеме.

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

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

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

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

person Mike Dinescu    schedule 20.09.2018