Технологии
DynamoDB
Как использовать DynamoDB для решения широкого круга задач по System Design
DynamoDB - это полностью управляемый, высокомасштабируемый сервис хранения пар ключ-значение, предоставляемый Amazon Web Services. Крутые маркетинговые слоганы... Но что это значит и почему это важно?
-
Полностью управляемый (fully-managed) - это означает, что AWS берет на себя все операционные аспекты управления базой данных. AWS занимается закупкой оборудования, конфигурацией, обновлением программного обеспечения и масштабированием инфраструктуры, позволяя разработчикам сосредоточиться исключительно на разработке приложения.
-
Высокомасштабируемый (highly-scalable) - DynamoDB способен обрабатывать огромные объемы данных и трафика. Система автоматически масштабируется вверх и вниз (scale up and down), адаптируясь к потребностям вашего приложения, без какого-либо простоя или ухудшения производительности.
-
Ключ-Значение (key-value) - DynamoDB является базой данных типа NoSQL, что означает отказ от традиционной реляционной модели баз данных. Вместо нее используется модель ключ-значение, позволяющая гибко хранить и извлекать данные.
Итог всей истории таков: DynamoDB невероятно прост в использовании и способен масштабироваться, поддерживая широкий спектр приложений. Особенно полезно помнить об этом для собеседований по проектированию систем - эта база данных практически удовлетворяет любым необходимым требованиям. Сейчас DynamoDB даже поддерживает транзакции, что устраняет один из главных прошлых недостатков.
Важно отметить, что DynamoDB не является проектом с открытым исходным кодом, поэтому мы не можем так же детально описать внутреннюю структуру системы, как делали это с открытыми технологиями вроде Kafka и Redis. Вместо этого мы сосредоточимся больше на взаимодействии с сервисом. Чтобы заглянуть глубже внутрь, нам придется полагаться на ограниченную информацию, которую AWS предоставляет в документации и официальной статье о DynamoDB.
В ходе этого разбора мы рассмотрим все, что вам потребуется знать о DynamoDB, чтобы уверенно отвечать на любые вопросы, касающиеся ее использования в интервью по System Design. По пути вы также получите практические знания, которые сможете применить в собственных проектах позже. Давайте приступим!
Часто кандидаты задают вопрос: "Можно ли вообще использовать DynamoDB на собеседовании?". Ответ простой - спросите своего интервьюера! Многие скажут да, ожидая, что вы знаете, как ей пользоваться. Другие могут сказать нет, предпочитая альтернативы с открытым исходным кодом, чтобы избежать зависимости от AWS. Как обычно бывает, лучше всего спросить заранее.
Модель данных
В DynamoDB данные организованы в таблицы, каждая из которых содержит множество элементов, представляющих отдельные записи. Это похоже на реляционную базу данных, но с некоторыми существенными отличиями, направленными на обеспечение масштабируемости и гибкости.
Таблицы (Tables) - выступают в качестве основной структуры данных в DynamoDB, каждая таблица определяется обязательным первичным ключом, уникальным образом идентифицирующим ее элементы. Таблицы поддерживают вторичные индексы, позволяющие выполнять запросы по атрибутам, отличным от первичного ключа, обеспечивая более универсальное извлечение данных.
Элементы (Items) - соответствуют строкам в реляционной базе данных и содержат коллекцию атрибутов. Каждый элемент обязательно имеет первичный ключ и может содержать до 400 КБ данных, включая все его атрибуты.
Атрибуты (Attributes) - пары ключ-значение, составляющие данные внутри элемента. Они могут различаться по типу, включая скалярные типы (строки, числа, булевы значения) и множественные типы (наборы строк, наборы чисел). Атрибуты также могут быть вложенными, позволяя создавать сложные структуры данных в рамках одного элемента.
Настройка DynamoDB проста: вы можете создать таблицы непосредственно в консоли AWS и сразу же начать вставлять данные. В отличие от традиционных РСУБД, DynamoDB является бессхемной базой, то есть вам не нужно определять схему перед вставкой данных. Это означает, что элементы одной и той же таблицы могут иметь разные наборы атрибутов, а новые атрибуты можно добавлять в элементы в любое время без влияния на существующие элементы. Такая бессхемная архитектура обеспечивает высокую гибкость, но требует тщательной проверки данных на уровне приложения, поскольку DynamoDB не гарантирует единообразия атрибутов среди элементов.
Рассмотрим таблицу пользователей users в DynamoDB, структурированную следующим
образом:
{
"PersonID": 101,
"LastName": "Иванов",
"FirstName": "Леонид",
"Phone": "123-555-432"
},
{
"PersonID": 102,
"LastName": "Петрова",
"FirstName": "Мария",
"Address": {
"Street": "123 Маркса",
"City": "Тверь",
"State": "Тверская область",
"ZIPCode": 12345
}
},
{
"PersonID": 103,
"LastName": "Сидоров",
"FirstName": "Дмитрий",
"Address": {
"Street": "123 Маркса",
"City": "Мирный",
"PostalCode": "443 234"
},
"FavoriteColor": "Синий"
}Каждый элемент представляет собой пользователя с различными атрибутами. Обратите
внимание, как некоторые пользователи имеют атрибуты, отсутствующие у других,
например, FavoriteColor. Это демонстрирует гибкость DynamoDB в управлении
атрибутами.
Хотя DynamoDB использует JSON для передачи данных, это всего лишь транспортный формат. Фактический формат хранения DynamoDB является закрытым, что позволяет пользователям сосредоточиться на моделировании данных, не углубляясь в сложности физического хранения данных.
Ключ партиционирования и ключ сортировки
Таблицы DynamoDB определяются первичным ключом, который может состоять из одного или двух атрибутов:
-
Ключ партиционирования (partition key) - одиночный атрибут, который вместе с ключом сортировки (если он присутствует) однозначно идентифицирует каждый элемент в таблице. DynamoDB использует значение ключа партиционирования для определения физического расположения элемента в базе данных. Это значение хэшируется для определения раздела, в котором хранится элемент.
-
Ключ сортировки (sort key) (необязательный) - дополнительный атрибут, который в сочетании с ключом партиционирования образует составной первичный ключ. Ключ сортировки используется для упорядочивания элементов с одинаковым значением ключа партиционирования, что позволяет эффективно выполнять запросы по диапазону и сортировку внутри раздела.
Во время собеседования важно четко указывать ключ партиционирования и, при необходимости, ключ сортировки при описании таблиц DynamoDB. Этот выбор важен для оптимизации производительности запросов и эффективности извлечения данных. Как и в любом другом хранилище данных, вы выбираете ключ партиционирования таким образом, чтобы оптимизировать наиболее распространенные запросы вашего приложения и обеспечить равномерное распределение данных по разделам. Если вам потребуется выполнение запросов по диапазону или сортировка, следует также задать ключ сортировки.
Например, если вы создаете простое приложение для группового чата, целесообразно
использовать chat_id в качестве ключа партиционирования и message_id в
качестве ключа сортировки. Таким образом, вы сможете эффективно запрашивать все
сообщения конкретной группы и сортировать их хронологически перед отображением
пользователям.
Заметьте, что мы используем монотонно увеличивающийся message_id вместо метки
времени (timestamp) в качестве ключа сортировки. Хотя временные метки кажутся
интуитивно понятными для упорядочивания сообщений, они не гарантируют
уникальности - несколько сообщений могли бы быть созданы в одну и ту же
миллисекунду. Монотонно возрастающий идентификатор (например,
автоинкрементируемый номер или UUID версии 1) обеспечивает как хронологический
порядок, так и уникальность. Идентификаторы могут создаваться с использованием
методов вроде:
- Автоинкрементируемых счетчиков внутри каждого раздела
- UUID на основе timestamp (UUID v1)
- Snowflake ID
- ULID
Но что именно происходит под капотом?
DynamoDB применяет комбинацию согласованного хеширования (consistent hashing) и B-деревьев (B-trees) для эффективного управления распределением и извлечением данных:
Согласованное хеширование для ключей партиционирования: Физическое расположение данных определяется ключом партиционирования. Мы применяем согласованное хеширование к этому ключу, чтобы определить, какой узел кластера DynamoDB сохранит элемент. Это гарантирует равномерное распределение данных по всему кластеру.
B-деревья для ключей сортировки: Внутри каждого раздела DynamoDB организует элементы в структуру данных B-дерево, индексированную по ключу сортировки. Это позволяет эффективно выполнять запросы по диапазону и извлекать отсортированные данные внутри раздела.
Операции с составными ключами: Когда выполняется запрос с обоими ключами, DynamoDB сначала использует хэш ключа партиционирования, чтобы найти нужный раздел, а затем применяет ключ сортировки для обхода B-дерева и нахождения конкретных элементов.
Этот двухуровневый подход позволяет DynamoDB одновременно обеспечивать горизонтальное масштабирование (через партиционирование) и эффективную обработку запросов внутри разделов (благодаря индексации с помощью B-деревьев). Именно такое сочетание позволяет DynamoDB обрабатывать огромные объемы данных, обеспечивая при этом быстрое и предсказуемое выполнение запросов, использующих как ключи партиционирования, так и ключи сортировки.
Вторичные индексы
Что делать, если вам нужно запрашивать ваши данные по атрибуту, который не является ключом партиционирования? Здесь вступают в дело вторичные индексы. DynamoDB поддерживает два типа вторичных индексов:
-
Глобальные вторичные индексы (Global Secondary Index - GSI) - Индекс с ключом партиционирования и необязательным ключом сортировки, отличающимся от ключа партиционирования основной таблицы. Глобальные вторичные индексы позволяют вам запрашивать элементы на основании атрибутов, отличающихся от ключа партиционирования исходной таблицы. Поскольку GSIs используют разные ключи партиционирования, данные хранятся на совершенно отдельных физических разделах относительно базовой таблицы и реплицируются отдельно.
-
Локальные вторичные индексы (Local Secondary Index - LSI) - Индексы с таким же ключом партиционирования, как и первичный ключ таблицы, но с другим ключом сортировки. LSI позволяют выполнять запросы диапазонов и сортировку данных внутри одного раздела. Так как локальные индексы используют тот же самый ключ партиционирования, что и базовая таблица, они физически располагаются на тех же разделах, что и индексируемые ими элементы.
Понимание разницы физического хранения между глобальными (GSIs) и локальными (LSI) вторичными индексами имеет большое значение. GSIs поддерживают собственные отдельные разделы и реплики, что позволяет значительно расширить гибкость запросов, однако требует дополнительного объема хранилища и вычислительных ресурсов. Напротив, LSI хранятся совместно с элементами базовой таблицы, что делает их более эффективными для запросов внутри раздела, но ограничивает их универсальность.
Практически, в обоих случаях создание этих индексов осуществляется через консоль AWS или с помощью AWS SDK. После настройки DynamoDB самостоятельно заботится о поддержании и обновлении индексов при изменении данных.
Вам нужно использовать GSI в ситуациях, когда необходимо эффективно запрашивать
данные по атрибуту, который не является ключом партиционирования. Например,
предположим, у вас есть таблица чатов с сообщениями для вашего приложения-чата.
Тогда основным ключом партиционирования вашей таблицы скорее всего будет
chat_id, а ключом сортировки - message_id. Таким образом, вы легко можете
получать все сообщения заданного чата, отсортировав их по времени. Но что если
вы хотите показать пользователям все отправленные ими сообщения во всех чатах?
Теперь вам понадобится GSI с ключом партиционирования user_id и ключом
сортировки message_id.
LSI полезны тогда, когда вам необходимо выполнять запросы по диапазону или
сортировку внутри отдельного раздела по другому атрибуту, нежели ключ
сортировки. Возвращаясь к нашему примеру с приложением для чатов, мы уже можем
сортировать сообщения по полю message_id внутри чат группы. Однако что, если
нам потребуется выбрать сообщения с наибольшим количеством вложений в рамках
конкретной группы? Для решения этой задачи можно создать LSI по атрибуту
num_attachments, чтобы быстро находить сообщения с большим числом
прикрепленных файлов.
| Функция | GSI | LSI |
|---|---|---|
| Определение | Индекс с другим ключом партиционирования, нежели в главной таблице | Индекс с таким же ключом партиционирования, что и в главной таблице, но с другим ключом сортировки |
| Когда использовать | Когда нужны запросы по атрибутам, которые не входят в первичный ключ | Когда нужна дополнительная сортировка при запросе по первичному ключу |
| Ограничения по размеру | Нет ограничений по размеру элементов в индексе | Ограничено до 10 ГБ на ключ раздела |
| Производительность | Отдельная емкость (capacity units) чтения/записи от базовой таблицы | Переиспользует емкость (capacity units) чтения/записи базовой таблицы |
| Согласованность | Только в конечном итоге (eventual consistency) | Поддерживает как согласованность в конечном счете (по умолчанию), так и сильную согласованность (strong consistency) при чтении |
| Удаление | Удаление GSI (глобального вторичного индекса) не влияет на элементы основной таблицы | Удаление LSI (локального вторичного индекса) невозможно без удаления основной таблицы |
| Максимальное количество | До 20 глобальных вторичных индексов (GSIs) на таблицу | До 5 локальных вторичных индексов (LSIs) на таблицу |
| Примеры случаев использования | Используйте GSI для глобального поиска по всем разделам, например, для поиска по электронной почте в базе пользователей | Используйте LSI для локального поиска внутри разделов, например, для нахождения последних заказов в разделе клиента |
Но что же фактически происходит внутри?
Вторичные индексы в DynamoDB реализованы как отдельные таблицы, которые автоматически поддерживаются системой:
- Глобальные вторичные индексы (GSI):
- Каждый GSI по сути является отдельной таблицей со своей собственной схемой партиционирования.
- При добавлении, обновлении или удалении элемента в основной таблице DynamoDB асинхронно обновляет GSI.
- GSI используют тот же механизм согласованного хеширования, что и основная таблица, но с другими ключами партиционирования и сортировки.
- Это позволяет эффективно запрашивать атрибуты не входящие в первичный ключ, по всем разделам.
- Локальные вторичные индексы (LSI):
- LSI размещаются совместно с разделами основной таблицы, используя общий ключ партиционирования.
- Они поддерживают отдельную структуру B-дерева в каждом разделе, индексированную по ключу сортировки LSI.
- Обновления LSI выполняются синхронно с обновлениями основной таблицы, обеспечивая строгую согласованность.
- Поддержка индексов:
- DynamoDB автоматически распространяет изменения из основной таблицы на все вторичные индексы.
- Для глобальных вторичных индексов (GSI) эта синхронизация в конечном итоге становится согласованной, тогда как для локальных вторичных индексов (LSI) она остается строго согласованной.
- Система управляет дополнительной пропускной способностью записи, необходимой для обновления индексов.
- Обработка запросов:
- Когда запрос использует вторичный индекс, DynamoDB направляет запрос в соответствующую таблицу индекса (для GSI) или структуру индекса (для LSI).
- Затем система применяет механизмы ключей партиционирования и сортировки для эффективного извлечения запрашиваемых данных.
Доступ к данным
Мы уже немного затронули этот вопрос ранее, но давайте подробнее рассмотрим, как можно получать доступ к данным в DynamoDB. Существует два основных способа доступа к данным в DynamoDB: операции сканирования (Scan) и запросы (Query).
Операция сканирования (Scan) - считывает каждый элемент в таблице или индексе и возвращает результаты постранично. Операции сканирования полезны, когда вам нужно прочитать все элементы в таблице или индексе, однако они неэффективны для больших объемов данных из-за необходимости чтения каждого элемента и должны использоваться лишь в крайнем случае.
Операция запроса (Query) - извлекает элементы на основании первичного ключа или атрибутов ключей вторичных индексов. Запросы гораздо эффективнее операций сканирования, поскольку читают только те элементы, которые соответствуют указанным условиям ключа. Запросы также позволяют выполнять диапазонные запросы по ключу сортировки.
В отличие от SQL, DynamoDB не имеет структурированного языка запросов. Вместо этого вы будете использовать AWS SDK или консоль AWS для взаимодействия с базой данных. Давайте рассмотрим простой пример запроса из таблицы пользователей.
В SQL вы бы написали:
SELECT * FROM users WHERE user_id = 101Но в DynamoDB это было бы переведено в операцию запроса примерно следующим образом:
const params = {
TableName: "users",
KeyConditionExpression: "user_id = :id",
ExpressionAttributeValues: {
":id": 101,
},
};
dynamodb.query(params, (err, data) => {
if (err) console.error(err);
else console.log(data);
});Чтобы выполнить операцию сканирования, вы бы использовали метод scan вместо query.
Эквивалент сканирования в SQL:
SELECT * FROM usersВ DynamoDB операция сканирования:
const params = {
TableName: "users",
};
dynamodb.scan(params, (err, data) => {
if (err) console.error(err);
else console.log(data);
});Работая с Dynamo, вы обычно хотите избегать дорогостоящих операций сканирования везде, где это возможно. Именно здесь важную роль играет тщательное моделирование данных. Правильно выбрав ключ партиционирования и ключ сортировки, вы можете обеспечить эффективность и производительность ваших запросов.
При выполнении запросов к DynamoDB важно помнить, что по умолчанию вы считываете весь элемент (запись), в отличие от SQL, где можно выбрать конкретные поля. Это может оказаться затратным с точки зрения единиц потребления ресурсов чтения (read capacity units, RCU) и сетевого трафика, особенно для крупных элементов. Вам следует соответствующим образом нормализовать ваши данные, чтобы избежать ненужной передачи данных.
Например, представьте себе ситуацию, когда вы проектируете сервис наподобие Yelp
и вам необходимо хранить подробности о предприятиях и отзывы. У вас может быть
таблица предприятий business с такими атрибутами, как business_id, name,
address, city, state, zip, category, и subcategory. Хотя вы могли бы
сохранить список отзывов непосредственно в таблице business, это означало бы,
что всякий раз, когда вам понадобится базовая информация о предприятии, вам
придется читать всю запись, даже если вам нужны только название и адрес. Вместо
этого разумнее будет перенести отзывы в отдельную таблицу и обращаться к ней по
бизнес-ID.
Теорема CAP
Обычно на этапе сбора нефункциональных требований вы принимаете некоторые ранние решения относительно согласованности и доступности. Поэтому важно выбрать базу данных, которая соответствует этим требованиям.
Большинство кандидатов выбирают DynamoDB, когда им требуются высокая доступность и масштабируемость. Это не ошибка, но точно так же, как традиционный спор SQL против NoSQL, это устаревший подход.
DynamoDB может быть настроен для поддержки двух разных моделей согласованности: согласованности в конечном счете и сильной согласованности.
Согласованность в конечном счете - эта модель согласованности используется по умолчанию в DynamoDB. Она обеспечивает наивысшую доступность и наименьшую задержку, но может привести к чтению устаревших данных. Это означает, что если вы записали данные, а затем сразу прочитали их, вы можете не увидеть обновленные данные немедленно. С такой конфигурацией DynamoDB представляет собой систему типа AP, демонстрирующую свойства BASE.
Сильная согласованность - эта модель гарантирует, что все операции чтения отражают самую последнюю запись. Это достигается за счет увеличения задержки и потенциально снижения доступности. С такой конфигурацией DynamoDB является системой типа CP, демонстрирующей свойства ACID.
Еще раз повторимся, это всего лишь простое изменение конфигурации в консоли AWS или через SDK, которое означает, что вы можете использовать DynamoDB в широком спектре сценариев, включая те, где необходима сильная согласованность, например, в банковских приложениях или системах бронирования билетов.
Но что именно происходит под капотом?
Модели согласованности DynamoDB реализуются посредством распределенной архитектуры и механизмов репликации:
Операции чтения с согласованностью в конечном счете (по умолчанию):
- Операции записи сначала записываются в основную реплику, а затем асинхронно реплицируются на вторичные реплики
- Запросы чтения могут обслуживаться любой репликой, которая может еще не иметь последней версии данных
- Фоновое процессы постоянно синхронизируют данные между репликами
- Занимает меньше емкости чтения (0,5 RCU на каждые 4 КБ) и обеспечивает меньшую задержку
Сильная согласованность операций чтения:
- Такие операции чтения направляются непосредственно на ведущий узел для раздела
- Ведущий узел гарантирует наличие самой актуальной версии данных перед отправкой ответа
- Занимает больше емкости чтения (1 RCU на каждые 4 КБ) и может иметь большую задержку
- Предоставляет самую свежую версию данных, отражающую все успешные записи
Архитектура и масштабируемость
Масштабируемость
DynamoDB масштабируется путем автоматического шардирования и балансировки нагрузки. Когда сервер достигает предела емкости, данные автоматически перераспределяются. Согласованное хэширование обеспечивает равномерное распределение данных по узлам, уравновешивая трафик и нагрузку.
Глобальная инфраструктура AWS усиливает эту масштабируемость. Глобальные таблицы позволяют осуществлять репликацию в режиме реального времени по регионам, позволяя выполнять локальные операции чтения и записи по всему миру. Это снижает задержку и улучшает качество обслуживания пользователей. DynamoDB также интегрируется по нескольким зонам доступности в каждом регионе, таким образом избыточность обеспечивает непрерывную работу сервиса и долговечность данных.
Выбор правильных регионов и зон важен, потому что это оптимизирует производительность и также помогает соблюсти нормативные требования, учитывая близость пользователей и требования регулирующих органов. Локальность данных в целом важна для уменьшения задержки и повышения производительности.
При разработке глобальных приложений на собеседовании часто достаточно упомянуть глобальные таблицы для межрегиональной репликации.
Отказоустойчивость и доступность
DynamoDB спроектирована так, чтобы обеспечивать высокую доступность и отказоустойчивость благодаря своей распределенной архитектуре и механизмам репликации данных. Сервис автоматически реплицирует данные по нескольким зонам доступности в пределах региона, чтобы гарантировать сохранность данных и их доступность даже в случае аппаратных или сетевых сбоев.
Вы легко можете настроить уровень избыточности ваших данных, задав количество реплик чтения и записи для каждой таблицы. Это позволит вам поддерживать несколько копий ваших данных в разных зонах доступности, повышая надежность хранения данных и их доступность.
Под капотом DynamoDB использует кворумную систему репликации, чтобы обеспечить как согласованность данных, так и их хранение. Операции записи требуют подтверждения большинства реплик, прежде чем будут считаться успешно выполненными.
Для сильно согласованных операций чтения DynamoDB направляет запрос к основной реплике, гарантируя получение наиболее актуальной версии данных. Однако в режиме конечной согласованности запросы на чтение могут обслуживаться любыми репликами, что вследствие асинхронного характера репликации может привести к возвращению слегка устаревшей информации.
Безопасность
Данные шифруются по умолчанию в состоянии покоя в DynamoDB, поэтому ваши данные защищены даже тогда, когда они не используются. Вы также можете включить шифрование в процессе передачи, чтобы убедиться, что данные зашифрованы при перемещении между DynamoDB и вашим приложением.
DynamoDB интегрирован с управлением идентификацией и доступом Amazon Web Services (IAM), что позволяет настраивать детализированный контроль доступа к вашим данным. Вы можете создавать политики IAM, которые определяют, кто может получить доступ к вашим данным и какие действия они могут выполнять. Это позволяет ограничить доступ к вашим данным только теми лицами, которым это действительно необходимо.
Кроме того, вы можете использовать конечные точки виртуальной частной сети (VPC) для безопасного доступа к DynamoDB изнутри вашей VPC без раскрытия данных в общедоступном интернете. Это добавляет дополнительный уровень защиты, гарантируя, что ваши данные доступны только изнутри вашей VPC.
Во время интервью, работая с чувствительными пользовательскими данными, может быть полезно отметить, что вы знаете, что DynamoDB по умолчанию шифрует данные и что вы можете включить шифрование при передаче, если это необходимо. За исключением этого, вся остальная информация, вероятно, будет излишней.
Цены
Возможно, цена кажется совершенно несущественным фактором для интервью, но потерпите, понимание модели ценообразования вводит четкие ограничения на вашу архитектуру.
Существует две модели ценообразования для DynamoDB: оплата по требованию и фиксированная емкость. Модель оплаты по требованию взимает плату за каждое обращение, что делает ее подходящей для непредсказуемых нагрузок. Фиксированная емкость, напротив, требует от пользователей указывать единицы емкости чтения и записи, которые оплачиваются почасово. Этот вариант более экономичен для предсказуемых рабочих нагрузок, но может привести к недоиспользованию мощности в периоды низкой активности.
Цена зависит от того, что Amazon называет единицами емкости чтения и записи. Их можно рассматривать как меру того, сколько данных вы можете считать или записать за секунду из вашей таблицы DynamoDB.
Одна единица емкости чтения позволяет считывать до 4 Кб данных в секунду. Одна единица емкости записи позволяет записывать до 1 Кб данных в секунду.
| Функция | Цена | Детали |
|---|---|---|
| Единица емкости чтения (RCU) | $1.12 за миллион операций чтения (каждая по 4 КБ). | Обеспечивает одну сильно согласованную операцию чтения в секунду для элементов размером до 4 КБ или две операции чтения с конечной согласованностью в секунду. |
| Единица емкости записи (WCU) | $5.62 за миллион операций записи (каждая по 1 КБ). | Обеспечивает одну операцию записи в секунду для элементов размером до 1 КБ. |
Хотя сама стоимость не особо интересна на собеседовании, полезно иметь общее представление о цифрах. Один шард AWS поддерживает 1000 единиц емкости чтения и 1000 единиц емкости записи. Это значит, что один шард способен обрабатывать чтение объемом до 4 МБ в секунду и запись объемом до 1 МБ в секунду. Несмотря на то, что автоматическое разделение и автомасштабирование происходят автоматически, эти числа могут быть полезными для проверки возможности приложения справиться с ожидаемой нагрузкой без возникновения нереалистично высоких расходов.
Например, если вы планируете хранить просмотры на YouTube в DynamoDB, вы можете рассчитать, что каждая запись состоит всего из userId, videoId и отметки времени, занимая около 100 байт. Это означает, что вы сможете сохранять 10 000 просмотров в секунду на одном шарде. Если вы ожидаете 10 000 000 просмотров в секунду, вам потребуется около 1000 шардов для обработки записи, что обойдется примерно в $150 000 в день исходя из текущих цен.
Продвинутые возможности
DAX (ускоритель DynamoDB)
Забавный факт: DynamoDB поставляется встроенным кешем в памяти, называемым ускорителем DynamoDB (DynamoDB Accelerator, DAX). Таким образом, может не потребоваться добавлять дополнительные сервисы (например, Redis, Memcached) в свою архитектуру - достаточно просто активировать DAX.
DAX - это сервис кэша, предназначенный для улучшения производительности DynamoDB предоставляющий отклик менее чем за миллисекунду для рабочей нагрузки с интенсивным чтением. Будучи родным для DynamoDB, DAX не требует изменений в коде приложения; его просто нужно включить на ваших таблицах.
DAX работает как кэш с прямым чтением и прямой записью, что означает, что он автоматически сохраняет результаты чтения из таблиц DynamoDB и передает их непосредственно приложениям, а также записывает данные одновременно в кэш и лежащую в основе таблицу DynamoDB. Элементы кэша становятся недействительными, когда соответствующие данные в таблице обновляются или когда размер кэша достигает своего лимита. Для более подробной информации о работе DAX, смотрите эту статью от AWS.
DAX может быть настроен либо как кеш объектов, либо как кеш запросов. Кеш
объектов хранит результаты операций GetItem, в то время как кеш запросов
хранит результаты операций Query и Scan. Подобно DynamoDB, DAX также может
быть настроен для конечной или сильной согласованности, чтобы соответствовать
специфическим требованиям вашей системы.
Потоки (Streams)
DynamoDB также имеет встроенную поддержку захвата изменений данных (Change Data Capture, CDC) через потоки DynamoDB. Потоки регистрируют изменения в объектах таблицы и делают их доступными для обработки в режиме реального времени. Любое событие изменения в таблице, такое как вставка, обновление или удаление, фиксируется в потоке как потоковая запись для последующего использования приложениями.
Это может использоваться для различных сценариев, таких как запуск Lambda-функций в ответ на изменения в базе данных, поддержание реплики базы данных в другой системе или обработки аналитики в реальном времени.
Согласование с Elasticsearch - потоки DynamoDB могут использоваться для синхронизации индекса Elasticsearch с таблицей DynamoDB. Это удобно для построения функциональности поиска поверх данных DynamoDB.
Аналитика в реальном времени - обрабатывая потоки DynamoDB с помощью Kinesis Data Firehose, вы можете загружать данные в Amazon S3, Redshift или Elasticsearch для анализа в реальном времени.
Уведомления об изменениях - потоки DynamoDB можно использовать для запуска функций Lambda в ответ на изменения в базе данных. Это может пригодиться для отправки уведомлений, обновления кэшей или выполнения других действий в ответ на изменения данных.
Использование DynamoDB на собеседованиях
Когда целесообразно применять
На собеседованиях вы часто можете обосновать выбор DynamoDB практически для любых нужд слоя хранения данных. Это высокопроизводительная, надежная база данных, поддерживающая транзакции и обеспечивающая отклик менее одной миллисекунды. Дополнительные функции, такие как DAX для кэширования и потоки DynamoDB для согласованности между хранилищами, делают ее еще мощнее. Так что, если ваш интервьюер разрешает использовать DynamoDB, это, скорее всего, отличный вариант.
Однако важно понимать, когда лучше не использовать DynamoDB из-за ее специфических ограничений.
Ограничения
Есть несколько причин, почему вы можете предпочесть другую базу данных (кроме причины, что вы больше знакомы с другим инструментом):
-
Cтоимость: модель ценообразования DynamoDB основана на операциях чтения и записи плюс хранимых данных, что может стать дорогим удовольствием при больших объемах. Если вам нужно сотни тысяч записей в секунду, затраты могут превысить преимущества.
-
Сложные паттерны запросов: если ваша система требует сложных запросов, таких как соединения или многотабличные транзакции, DynamoDB может не подойти. Она отлично справляется с простыми запросами, но испытывает трудности с более сложными операциями.
-
Ограничения моделирования данных: DynamoDB требует внимательного подхода к моделированию данных для эффективной работы, оптимизированного для структур ключ-значение и документов. Если вы регулярно используете глобальные вторичные индексы (GSI) и локальные вторичные индексы (LSI), реляционная база данных вроде PostgreSQL может быть лучшим выбором.
-
Привязанность к поставщику услуг: выбор DynamoDB означает привязку к AWS. Многие интервьюеры не захотят зависеть от поставщика, поэтому вам, возможно, придется рассмотреть альтернативы с открытым исходным кодом.
Заключение
Вот мы и рассмотрели все самое важное. База данных DynamoDB универсальна, мощна и доставляет удовольствие при работе с ней. На собеседовании это хороший выбор для большинства случаев, но вам следует учитывать ограничения и хорошо разбираться в том, как она функционирует, включая умение выбирать подходящую модель данных, ключ партиционирования, ключ сортировки, вторичные индексы и знать, когда включать расширенные функции, такие как DAX и потоки.
Наконец, помните, что DynamoDB даже поддерживает ACID и транзакции, поэтому старый спор SQL против NoSQL нерелевантен.