Схема таблиц / индексов DynamoDB для запроса многозначных атрибутов - PullRequest
0 голосов
/ 07 декабря 2018

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

{ 
  userId: "08074c7e0c0a4453b3c723685021d0b6",  // partition key
  email: "foo@foo.com",
  ... other attributes ...
}

Когда новый пользователь регистрируется или если пользователь хочет найти другого пользователя по адресу электронной почты, мы должны вместо этого искать пользователей по emailиз userId.С текущей схемой это просто: просто используйте глобальный вторичный индекс с email в качестве ключа раздела.

Но мы хотим включить несколько адресов электронной почты для каждого пользователя и DynamoDB Query операция не поддерживает List -тип KeyConditionExpression.Поэтому я взвешиваю несколько вариантов, чтобы избежать дорогостоящей операции Scan каждый раз, когда пользователь регистрируется или хочет найти другого пользователя по адресу электронной почты.

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

  1. Добавить столбец ключа сортировки (например, itemTypeAndIndex), чтобы разрешить несколько элементов для userId.

{ userId: "08074c7e0c0a4453b3c723685021d0b6", // partition key itemTypeAndIndex: "main", // sort key email: "foo@foo.com", ... other attributes ... }

Если пользователь добавляет второе, третье и т. Д. Электронное письмо, а затем добавляет новый элемент для каждого электронного письма, например:

{ userId: "08074c7e0c0a4453b3c723685021d0b6", // partition key itemTypeAndIndex: "Email-2", // sort key email: "bar@bar.com" // no more attributes }

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

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

Если нам нужно удалить пользователя, нам придется удалить всепредметы для этого userId.Если нам нужно объединить двух пользователей, то нам придется объединить все элементы для этого userId.

Тот же подход (новые элементы с одинаковыми userId, но разными ключами сортировки)может использоваться для других данных «1 пользователь имеет множество значений», которые должны быть Query -able

Это хороший способ сделать это?Есть ли лучший способ?

1 Ответ

0 голосов
/ 07 декабря 2018

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

  1. Использование ключа сортировки для идентификатора электронной почты приведет к созданию дублированных записей для того же пользователя, т.е. еслипользователь зарегистрировал 5 электронных писем, что подразумевает 5 записей в вашей таблице с той же схемой и атрибутом, за исключением атрибута email-id.
  2. Что если в будущем появится новый вариант использования, где теперь вы также хотитепоиск пользователя на основе какого-либо другого атрибута (например, номера сотового телефона, предполагая, что у пользователя может быть более одного номера сотового телефона)
  3. У DynamoDB есть жесткое ограничение числа вторичных индексов вы можете создать для таблицы, т. е. 5

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


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

Option 1. DynamoDB в качестве основного хранилища и AWS Elasticsearch в качестве дополнительного хранилища [ Предпочитается ]

  1. Хранить записи пользователейв таблице DynamoDB (назовем ее UserTable ), как и когда пользователь регистрируется.
  2. Включение потоков таблицы DynamoDB в таблице UserTable .
  3. СозданиеЛямбда-функция AWS, которая читает из потока таблицы и сохраняет записи в AWS Elasticsearch.

Теперь в вашем приложении используйте DynamoDB для извлечения записей пользователя из id.Для всех других критериев поиска (например, поиск по emailId, номеру телефона, почтовому индексу, местоположению и т. Д.) Извлеките записи из AWS Elasticsearch.AWS Elasticsearch по умолчанию индексирует все атрибуты вашей записи, поэтому вы можете выполнять поиск по любому полю в течение миллисекунды с задержкой.

Option 2. Использовать AWS Aurora [Менее предпочтительное решение]

Если ваше приложение имеет реляционный вариант использования, в котором данные связаны, вы можете рассмотреть этот вариант.Просто для справки: Аврора - это база данных SQL.Поскольку это реляционное хранилище, вы можете организовать записи в несколько таблиц и объединить их на основе первичного ключа этих таблиц.



Я предложу для 1-го варианта:

  1. DynamoDB предоставит вам надежное, высокодоступное первичное хранилище с низкой задержкой для вашего приложения.
  2. AWS Elasticsearch будет выступать в качестве вторичного хранилища, которое также является долговечным, масштабируемым и с малой задержкой.
  3. С AWS Elasticsearch вы можете запустить любой поисковый запрос на вашей таблице.Вы также можете сделать аналитику по данным. Kibana UI предоставляется "из коробки", который вы можете использовать для построения аналитических данных на приборной панели, например: (как растет число пользователей, сколько пользователей принадлежит определенному местоположению, распределение пользователей по городу /штат / страна и т. д.)
  4. С потоками DynamoDB и AWS Lambda вы будете синхронизировать эти две базы данных почти в реальном времени [в течение нескольких миллисекунд]
  5. Ваше приложение будет масштабируемым и функция поискаможет быть дополнительно улучшена для фильтрации по многоуровневым атрибутам.[Один из таких примеров: поиск всех пользователей, принадлежащих к данному городу]

Сказав это, теперь я оставлю это на ваше усмотрение.?

...