Эксплуатация
8. Эксплуатация
8.1. Безопасность
Если вы пришли из мира реляционных баз данных, ваша ментальная модель безопасности выглядит так:
- Есть один "супер-пользователь" БД (например,
app_user), прописанный в конфиге бэкенда. - Этот пользователь имеет права
ALL PRIVILEGESили хотя быSELECT/UPDATEна всю таблицу. - Вся логика разделения доступа ("Алиса видит только свои заказы") живет в вашем коде. Вы обязаны не забыть написать
WHERE user_id = 'Alice'в каждом SQL-запросе.
Проблема: Если хакер ломает ваш бэкенд (получает RCE) или джуниор (или ИИ-агент) забывает добавить WHERE в новом API-методе - вся база утекает. Злоумышленник через вашего app_user выкачивает данные всех клиентов.
DynamoDB предлагает фундаментально другой подход: безопасность вшита в инфраструктуру, а не в код.
Идентификация без паролей (IAM)
В DynamoDB нет логинов и паролей. Вообще. База данных "не знает", кто к ней подключается. Она доверяет только AWS IAM (Identity and Access Management). Каждый запрос подписывается криптографическими ключами (SigV4).
Это означает, что права доступа выдаются ролям, а не людям.
- Ваша Lambda-функция имеет IAM-роль.
- Ваш EC2-инстанс имеет IAM-роль.
- Мобильное приложение получает временные IAM-credentials через AWS Cognito.
Fine-Grained Access Control (FGAC)
Главная киллер-фича - это возможность ограничить доступ на уровне конкретных строк (Items) и колонок (Attributes) прямо в политике доступа AWS, не написав ни строчки кода на Python или Java.
1. Безопасность на уровне строк (Row-Level Security)
Представьте мульти-тенантное SaaS-приложение. У вас миллион пользователей в одной таблице AppTable. Как гарантировать, что пользователь с ID 123 никогда, ни при каких обстоятельствах не прочитает данные пользователя 456?
В IAM есть условие dynamodb:LeadingKeys. Оно работает как автоматический WHERE на уровне облака.
Сценарий: Мобильное приложение обращается к базе напрямую (или через тонкую Lambda). Мы выдаем ему IAM-политику, которая гласит: "Разрешено делать GetItem, НО ТОЛЬКО ЕСЛИ Partition Key совпадает с ID этого пользователя".
{
"Effect": "Allow",
"Action": [
"dynamodb:GetItem",
"dynamodb:Query",
"dynamodb:PutItem"
],
"Resource": "arn:aws:dynamodb:us-east-1:1234567890:table/AppTable",
"Condition": {
"ForAllValues:StringEquals": {
// Магия здесь:
// Разрешаем доступ, только если PK равен ID пользователя (из токена Facebook/Google/Cognito)
"dynamodb:LeadingKeys": ["${www.amazon.com:user_id}"]
}
}
}
Результат: Даже если вы допустите баг в коде и попытаетесь запросить чужой ключ, сама база данных отклонит запрос с ошибкой AccessDeniedException. Это "защита от дурака" (и от взлома) на самом низком уровне.
2. Безопасность на уровне атрибутов (Attribute-Level Security)
Иногда вам нужно дать доступ к строке, но скрыть чувствительные поля. Сценарий: У вас есть служба поддержки. Операторы должны видеть профиль пользователя (имя, телефон, историю заказов), чтобы помогать клиентам. Но они не должны видеть атрибут salary (зарплата) или passport_hash.
В SQL вы бы создавали VIEW или фильтровали поля в бэкенде. В DynamoDB вы используете условие dynamodb:Attributes.
{
"Effect": "Deny",
"Action": "dynamodb:GetItem",
"Resource": "arn:aws:dynamodb:us-east-1:1234567890:table/Users",
"Condition": {
"ForAllValues:StringEquals": {
// Запрещаем читать, если в списке запрашиваемых полей есть 'salary'
"dynamodb:Attributes": ["salary", "secret_question"]
}
}
}
Теперь, если приложение поддержки попытается сделать SELECT * (Scan или GetItem без проекции), DynamoDB вернет ошибку. Приложение обязано явно вернуть только разрешенные поля.
Шифрование
Здесь всё просто, потому что AWS делает это за вас.
- In Transit: Все запросы к API DynamoDB ходят только по HTTPS. Перехватить трафик "посередине" нельзя.
- At Rest: Данные на дисках AWS зашифрованы всегда. Вы не можете это отключить.
- AWS Owned Key (по умолчанию): Ключ шифрования управляется AWS. Бесплатно, прозрачно.
- AWS KMS (Customer Managed Key): Вы создаете свой мастер-ключ в KMS. Это нужно, если у вас строгий комплаенс (например, вы хотите иметь право "отозвать" ключ и сделать данные нечитаемыми даже для инженеров AWS).
Сетевая безопасность
По умолчанию DynamoDB - это публичный сервис. Когда ваш сервер (из частной сети) идет в DynamoDB, трафик выходит через NAT Gateway в публичный интернет (хоть и не покидает сеть AWS), а потом возвращается обратно.
Это создает две проблемы:
- Безопасность: Трафик формально покидает вашу приватную подсеть.
- Деньги: Вы платите за NAT Gateway (за каждый гигабайт трафика). При больших объемах это больно.
Решение: VPC Gateway Endpoint
Это "черный ход" из вашей VPC прямо в DynamoDB.
- Безопасность: Трафик никогда не покидает приватную сеть Amazon. Вы можете настроить политику так, чтобы к вашей таблице можно было обратиться только из вашей VPC.
- Экономия: Трафик через Gateway Endpoint бесплатен. Вы не платите за гигабайты.
- Простота: Не нужно менять код. DNS-имя
dynamodb.us-east-1.amazonaws.comпросто начинает резолвиться во внутренние IP-адреса.
Вывод по безопасности: DynamoDB позволяет построить архитектуру Zero Trust. Вместо того чтобы защищать "периметр" (файрволы) и надеяться на идеальный код бэкенда, вы настраиваете правила доступа прямо на данных. Даже если ваш сервер скомпрометирован, хакер упрется в жесткие IAM-лимиты: "этому серверу разрешено читать только заказы со статусом PENDING, и ничего больше".
Безопасность в DynamoDB
Вопросов: 5
8.2. Резервное копирование и восстановление
В мире классических баз данных бэкап - это всегда стресс.
- PostgreSQL/MySQL: Чтобы сделать надежный физический бэкап (без блокировок), вам нужно настраивать WAL-архивацию, использовать
pg_dump(который нагружает диск и процессор) или делать снапшоты дисков на уровне облака. - Влияние на прод: Часто бэкапы делают с реплики, потому что запуск бэкапа на мастере может "положить" производительность.
В DynamoDB бэкапы работают магически иначе. Они происходят на уровне системы хранения, вообще не затрагивая ваши RCU/WCU. Вы можете делать бэкап таблицы под нагрузкой 100 000 RPS, и ваше приложение не заметит даже микросекунды задержки.
Два типа бэкапов
DynamoDB предлагает два механизма защиты данных, которые закрывают разные потребности.
1. Point-in-Time Recovery (PITR) - "Машина времени"
Это ваша страховка от кривых рук и багов в коде. Представьте: вы выкатили релиз, в котором миграция данных случайно удалила email у 10% пользователей. Вы заметили это через 4 часа.
С традиционным "ночным бэкапом" вы бы потеряли данные за 20 часов (с момента прошлого бэкапа до момента аварии). С PITR вы можете восстановить состояние таблицы на любую секунду за последние 35 дней.
- RPO (Recovery Point Objective): 1 секунда.
- Как это работает: DynamoDB непрерывно пишет все изменения в скрытый лог.
- *Включение: Одной галочкой (или строкой в Terraform). Включите это прямо сейчас на всех прод-таблицах. Стоимость - копейки за гигабайт, а ценность бесконечна.
2. On-Demand Backup - "Вечные снапшоты"
Это классические полные бэкапы.
- Зачем: Для долгосрочного хранения. Например, закон требует хранить данные 5 лет. PITR хранит только 35 дней.
- Интеграция с AWS Backup: Вы можете настроить автоматическое создание таких снапшотов по расписанию, копирование их в другой регион (Disaster Recovery) и перемещение в холодное хранилище (Cold Storage) для экономии денег.
Главный архитектурный подвох: восстановление
Вот здесь многие архитекторы совершают ошибку, считая, что "Restore" работает как в SQL.
В MySQL вы можете сказать: "Восстанови бэкап в базу db_production", и она перезапишет испорченные данные. В DynamoDB восстановление (и из PITR, и из On-Demand) ВСЕГДА создает НОВУЮ таблицу.
Вы не можете восстановить данные "поверх" существующей таблицы.
Сценарий катастрофы:
- Таблица
Users(имя в проде) повреждена. - Вы запускаете Restore на состояние "час назад".
- DynamoDB создает новую таблицу. Вы обязаны дать ей новое имя, например
Users_Restored. - Процесс восстановления занимает время (от 10 минут до часов, зависит от объема).
- Финал: У вас есть живая, но битая таблица
Users(куда продолжает литься трафик!) и новая, здоровая таблицаUsers_Restored.
Как переключить трафик?
Это сложная инженерная задача, к которой надо быть готовым:
- Вариант А (быстрый, но грязный): Изменить конфиг приложения (переменную окружения
DYNAMODB_TABLE_NAME), чтобы оно начало писать вUsers_Restored.- Минус: Данные, записанные в старую таблицу
Usersза время восстановления, будут потеряны или их придется переносить вручную.
- Минус: Данные, записанные в старую таблицу
- Вариант Б (правильный, но сложный): Использовать Amazon Route 53 (если у вас глобальные таблицы) или абстракцию в коде, чтобы переключить запись.
- Вариант В (если нельзя менять конфиг): Удалить старую таблицу
Usersи сделать бэкап новой таблицыUsers_Restoredв таблицу с именемUsers. (Очень долго и опасно).
Совет: В ваших Lambda-функциях имя таблицы никогда не должно быть захардкожено (table = dynamodb.Table('Users')). Оно всегда должно браться из переменных окружения (os.environ['TABLE_NAME']). Только так вы сможете быстро переключить прод на восстановленную таблицу.
Удаление таблицы - это навсегда?
В старых версиях DynamoDB, если джуниор случайно запускал скрипт terraform destroy или нажимал "Delete Table" в консоли, таблица исчезала мгновенно. Вместе со всеми PITR бэкапами.
Сейчас (по умолчанию) AWS включает защиту, но вы должны знать о Backup on Delete. При удалении таблицы DynamoDB может автоматически создать финальный снапшот. Убедитесь, что эта опция не отключена в ваших IaC скриптах. Без неё удаление таблицы стирает и возможность сделать PITR-восстановление.
Бэкапы и восстановление в DynamoDB
Вопросов: 5
8.3. Глобальные таблицы
Как быть ближе к пользователю?
Вы запускаете вашу игру, и ваша база данных находится в Орегоне (us-west-2). Игроки в Портленде (рядом с Орегоном) счастливы (задержка 10 мс). Но тут игру скачивают в Берлине. Теперь игроки из Берлина жалуются на лаги - и они правы, их задержка до Орегона >150 мс.
Вам нужна архитектура Active-Active. Вы хотите, чтобы игроки из Берлина читали и писали в локальную копию базы во Франкфурте, а игроки из Портленда - в Орегоне. Эта архитектура в DynamoDB реализуется с помощью глобальных таблиц (Global Tables).
Механизм репликации и модели консистентности
Global Tables - это магия DynamoDB, но она работает в двух очень разных режимах, которые решают разные бизнес-задачи.
Режим 1: Multi-Region Eventual Consistency (MREC) (режим по умолчанию)
Это тот механизм, с которого начинались глобальные таблицы.
Как: Вы создаете таблицу в Орегоне (us-west-2), добавляете регион eu-central-1 (Франкфурт), и AWS автоматически настраивает двунаправленную асинхронную репликацию (построенную поверх DynamoDB Streams).
Зачем: Это невероятно быстро. Когда игрок пишет во Франкфурте, он получает 200 OK за ~10 мс. Данные асинхронно (обычно < 1 секунды) улетают в Орегон.
Разрешение конфликтов: Это асинхронная репликация. Что если два игрока в Токио и Берлине отредактируют один и тот же элемент в одно и то же время?
- DynamoDB использует простой механизм: побеждает последний записавший (Last Writer Wins - LWW).
- Каждая запись имеет внутренний timestamp. Когда реплики обмениваются данными, та запись, у которой timestamp позже, "побеждает" и перезаписывает другую.
- Проблема: Это просто, но это означает, что одна из записей (которая "проиграла") будет тихо потеряна. Это абсолютно неприемлемо для финансовых транзакций, бронирования билетов или управления инвентарем. Для
Set(user_name = 'Alex')- подходит.
Режим 2: Multi-Region Strong Consistency (MRSC)
Зачем: LWW (Режим 1) не подходит для критичных данных. Что, если вам нужно гарантировать, что ваш билет на концерт или бронь отеля уникальны глобально? Вам нужно, чтобы запись либо прошла глобально, либо не прошла нигде.
Как: Это более новый режим, который вы должны выбрать при создании глобальной таблицы (или при конвертации пустой таблицы).
-
Принцип работы: Этот режим полностью меняет механику. Когда вы пишете в один регион (например, Франкфурт):
- Этот регион (Франкфурт) становится координатором транзакции.
- Он не отвечает вам
200 OKнемедленно. Вместо этого он синхронно реплицирует это изменение как минимум в один другой регион (например, в ближайший - Лондон). - Он ждет подтверждения от этого другого региона.
- Только после получения подтверждения о записи в двух регионах (Франкфурт + Лондон) координатор (Франкфурт) возвращает
200 OKвашему приложению.
-
Ключевые преимущества:
- Глобальное строгое чтение: После того как
Writeвернул200 OK, Strongly Consistent Read (чтение со строгой консистентностью), выполненное в любом регионе-реплике (даже в Сиднее!), гарантированно вернет самую последнюю версию данных. - Глобальные условные записи:
ConditionExpression(условные выражения) всегда будут проверяться на основе глобально последней версии элемента, что предотвращает "гонки" (race conditions) между регионами.
- Глобальное строгое чтение: После того как
-
Компромиссы:
- Задержка (Latency): Ваша "быстрая" 10 мс запись (как в MREC) превращается в запись, чья задержка теперь равна RTT (Round Trip Time) до ближайшего другого региона. То есть запись во Франкфурте может занять 100+ мс (пока она "долетит" до Лондона/Дублина и вернется). Это гораздо медленнее, чем MREC.
- Доступность (Availability): Ваша запись теперь зависит от доступности как минимум двух регионов и сети между ними. Если Франкфурт не может "достучаться" ни до одного другого региона, ваша запись не пройдет.
- Стоимость: Этот режим значительно дороже, так как требует больше межрегионального трафика и координации.
-
Когда использовать: Только для низкочастотных, но сверхкритичных операций: регистрация уникального
usernameв глобальной игре, подтверждение финального платежа, бронирование одного оставшегося билета. 99% операций (обновление профиля, лайки) должны по-прежнему использовать быстрый MREC/LWW.
Глобальные таблицы и репликация
Вопросов: 5
8.4. Streams и Change Data Capture
DynamoDB может быть не просто базой данных. События в ней могут запускать другие события.
- Когда пользователь (
User) регистрируется, ему нужно отправить email. - Когда
Orderменяет статус на "Доставлен", нужно отправить нотификацию. - Когда
Productобновляется, нужно сбросить кэш и обновить поисковый индекс в Elasticsearch.
Традиционный подход (плохой): Писать cron job, которая раз в час сканирует таблицу orders на предмет изменений. Это медленно, дорого и создает пиковую нагрузку.
DynamoDB Streams - нервная система вашей таблицы.
DynamoDB Streams - это лог всех изменений в вашей таблице (Create, Update, Delete). Вы можете подписать на этот лог AWS Lambda.
Это позволяет создавать различные event-driven архитектуры:
DynamoDB (Write) -> Stream -> Lambda -> SNS/SES: Отправка нотификаций. Пользователь зарегистрировался - отправляем Welcome Email. Заказ сменил статус - пуш в мобильное приложение.DynamoDB (Write) -> Stream -> Lambda -> Другой сервис: Асинхронная бизнес-логика. При созданииOrderтриггерится Lambda, которая идет в сервис доставки и резервирует курьера.DynamoDB (Write) -> Stream -> Lambda: Агрегация в реальном времени. Обновление счетчиков, пересчет рейтингов, обновление материализованных представлений.
Streams vs Kinesis
- DynamoDB Streams: Встроенный, бесплатный. Хранит данные 24 часа. Идеален для триггеров Lambda.
- Kinesis Data Streams for DynamoDB: Отдельный платный сервис. Хранит данные до 1 года. Позволяет иметь множество потребителей (Lambda, Spark, etc.). Идеален для сложных аналитических пайплайнов.
8.5. Интеграция и экосистема
DynamoDB - это скальпель. Он идеально режет транзакционную нагрузку (OLTP), но совершенно непригоден для аналитики (OLAP) и сложного поиска. Если вы пытаетесь построить отчет "Продажи за квартал по регионам" или найти пользователя по части имени ("Ale..."), используя Scan в DynamoDB - вы забиваете гвозди микроскопом. Это дорого, медленно и убивает производительность продакшена.
AWS предлагает нативные интеграции, чтобы делегировать эти задачи специализированным сервисам.
S3: импорт, экспорт и холодные данные
Проблема стоимости хранения. Хранить данные в DynamoDB дорого ($0.25 за ГБ/мес). Хранить данные в S3 дешево ($0.023 за ГБ/мес). Разница в 10 раз. Если у вас есть терабайты логов или истории заказов за 5 лет, хранить их в горячей базе DynamoDB - это сжигать бюджет.
Решение: Native Export to S3. Раньше для выгрузки данных приходилось писать самописные скрипты на EMR или Glue, которые делали Scan таблицы, выжирая ваши драгоценные RCU.
Сейчас есть функция Export to S3.
- Zero Impact: Экспорт работает на уровне снапшотов (PITR). Он не потребляет RCU вашей таблицы и не влияет на производительность живого приложения.
- Форматы: DynamoDB JSON или Amazon Ion.
- Сценарий использования (Data Lake): Вы настраиваете периодический экспорт в S3. Там эти данные подхватывает AWS Athena. Аналитики пишут SQL-запросы к S3, строят отчеты в QuickSight, а ваш прод в DynamoDB даже не знает, что по его данным строят аналитику.
Решение: Import from S3. Обратная задача: вам нужно переехать с MongoDB или MySQL на DynamoDB. Если вы будете писать скрипт, который делает PutItem в цикле, вы разоритесь на WCU (Write Capacity Units). Функция Import from S3 позволяет залить CSV/JSON/ION файлы в новую таблицу.
- Экономика: Вы платите за гигабайты импортированных данных, а не за WCU. Это в разы дешевле стандартной записи.
Zero-ETL интеграция с OpenSearch
Проблема сложного поиска. DynamoDB умеет искать только по полному совпадению ключа (PK = '123') или диапазону (SK > 100). Она не умеет:
- Полнотекстовый поиск ("найти все товары с словом 'красный' в описании").
- Нечеткий поиск (Fuzzy search, опечатки).
- Гео-поиск ("найти рестораны в радиусе 5 км").
- Сложные агрегации ("средний чек по категориям").
Для этого существует OpenSearch (форк Elasticsearch).
Старый путь (The Hard Way). Раньше архитектура выглядела так: DynamoDB -> Streams -> Lambda -> OpenSearch. Вам приходилось писать и поддерживать Lambda-функцию, которая перекладывает данные. Нужно было обрабатывать ошибки, ретраи, следить за лагом стрима и версиями API OpenSearch. Это был "инфраструктурный клей", который постоянно ломался.
Новый путь: Zero-ETL Integration. AWS представил Zero-ETL интеграцию.
- Как это работает: Вы просто нажимаете кнопку в консоли, связывая таблицу DynamoDB и кластер OpenSearch Ingestion.
- Магия: AWS сам берет на себя репликацию данных. Без Lambda. Без написания кода. Без управления инфраструктурой.
- Результат: Данные появляются в OpenSearch через несколько секунд после записи в DynamoDB. Ваше приложение пишет в DynamoDB (для надежности), а читает из OpenSearch (для сложного поиска и фильтрации).
Итог: Используйте DynamoDB для того, для чего она создана (быстрая запись и чтение по ключу). Всё остальное (аналитика, архивация, сложный поиск) выгружайте в S3 и OpenSearch через нативные интеграции.
Zero-ETL интеграция с Amazon Redshift
Проблема: Вы хотите строить сложные финансовые отчеты, джойнить данные продаж с маркетинговыми кампаниями и строить дашборды в Tableau/PowerBI. DynamoDB этого не умеет. Athena (через S3) может быть медленной для интерактивных дашбордов. Вам нужен Data Warehouse.
Решение: Включаем Zero-ETL integration with Amazon Redshift.
- Как это работает: Это работает так же, как с OpenSearch. Вы связываете таблицу с кластером Redshift. AWS начинает реплицировать данные в фоновом режиме.
- Магия: В Redshift ваши данные появляются в виде обычных SQL-таблиц. Вы можете делать мощнейшие
JOIN,GROUP BYи оконные функции над терабайтами данных, которые изначально лежат в NoSQL. - Зачем это нужно, если есть S3 Export?: S3 Export - это снимок (Batch). Redshift Zero-ETL - это почти реальное время (near real-time). Ваш дашборд продаж отстает от продакшена всего на секунды, а не на сутки.
Kinesis Data Streams: когда обычных стримов мало
Ранее мы упоминали DynamoDB Streams. Это отличная штука для триггеров Lambda. Но у них есть ограничения:
- Данные хранятся только 24 часа. Если ваша Lambda упала на выходных, вы потеряли данные.
- Нельзя подключить много читателей (только 2 процесса одновременно).
Для серьезных Big Data задач (клики пользователей, телеметрия, финансовые потоки) используется интеграция с Kinesis Data Streams.
- Более долгая память: Данные могут храниться до 365 дней. Вы можете перемотать стрим на месяц назад и переиграть события.
- Fan-out: К одному потоку можно подключить 5-10 разных потребителей (один пишет в архив, второй считает фрод, третий обновляет кэш).
- Интеграция с Firehose: Kinesis умеет сам (без кода) складывать данные в S3, Redshift или Splunk, пачками, со сжатием и конвертацией форматов (например, JSON -> Parquet).
Итог по экосистеме
| Задача | Инструмент | Ключевое слово |
|---|---|---|
| OLTP (Приложение) | DynamoDB | Скорость (ms) |
| Search (Поиск) | OpenSearch | Нечеткий поиск |
| Data Lake (Архив) | S3 Export | Дешевизна |
| DW (Отчетность) | Redshift | Сложный SQL |
| Streaming (Big Data) | Kinesis | Глубина истории |
DynamoDB Streams и экосистема AWS
Вопросов: 6
8.6. Практика
Эксплуатация DynamoDB - безопасность, бэкапы, глобальные таблицы, Streams и интеграции
Вы продолжаете работу как CTO стартапа-конкурента Twitter. Вместе с Назаром разберите IAM и FGAC, бэкапы и восстановление, глобальные таблицы (MREC/MRSC), DynamoDB Streams и интеграции с S3, OpenSearch, Redshift.
Назар - ваш персональный ИИ-наставник. Он поможет закрепить материал через практику и ответит на ваши вопросы.
💡 Все обсуждения с ИИ могут быть прочитаны администратором для улучшения качества обучения.