open atlas
↑ К треку
AWS на практике AWS · 03 · 03

Управляемые базы данных: RDS, Aurora и DynamoDB

Управляемая реляционная (RDS/Aurora) против NoSQL (DynamoDB). RDS снимает патчинг, бэкапы и failover, но оставляет тебе схему и вертикальный потолок; DynamoDB меняет джойны на single-digit-ms на любом масштабе — если проектировать ключи, чтобы обходить hot partition.

AWS Middle ◷ 18 min
Уровень
ОсновыJuniorMiddleSenior

За неделю до запуска команда переключает базу RDS на Multi-AZ, читает на слайде «высокая доступность» и говорит залу: «теперь чтение прикрыто». Нет. Утренний всплеск трафика, read-heavy страница товара ползёт, единственный primary упёрт в 100% CPU, а совершенно здоровый standby сидит в другой AZ и не делает ничего, кроме ожидания смерти primary. Multi-AZ не обслужил ни одного чтения — standby это синхронный дублёр для failover, а не второй читатель. Решением в тот день была read replica; урок в том, что «HA» и «масштабирование чтения» — разные фичи, которые просто обе включают вторую копию базы, и путаница между ними стоит тебе аварии в самый загруженный час.

RDS и Aurora: управляемая реляционная, с тем, чем владеешь ты

Если ты хоть раз дебажил ночной пейджер из-за патча базы или вручную настраивал standby-репликацию в выходные, то поймёшь привлекательность управляемой реляционной — но «управляемый» покрывает конкретный список вещей, и именно в зазоре между тем, что берёт AWS, и тем, чем владеешь ты, прячутся production-инциденты.

Amazon RDS запускает знакомый тебе реляционный движок — PostgreSQL, MySQL, MariaDB, Oracle или SQL Server — и снимает операционную рутину. AWS владеет патчингом ОС и движка, автоматическими бэкапами и point-in-time recovery, а также механикой failover. Aurora — облачно-нативный вариант: MySQL- и PostgreSQL-совместимый движок, где AWS заменил слой хранения распределённым, log-structured парком, реплицируемым шесть раз через три AZ, что даёт более быстрый failover и read replicas, делящие один том хранения. В любом случае ты получаешь SQL: вторичные индексы, многострочные транзакции и джойны по нормализованным таблицам.

Чего AWS не снимает с тебя — это часть, которую джуны считают автоматической. Ты по-прежнему владеешь схемой, индексами и тюнингом запросов — отсутствующий индекс или N+1-паттерн запросов это твой баг, а не AWS, и управляемость не спасёт таблицу, делающую sequential scan. И реляционная на RDS масштабируется вертикально: ты делаешь инстанс больше. У этого есть потолок — самый большой класс инстанса это жёсткая стена, и записи фундаментально идут через один primary.

Две фичи постоянно смешивают, а смешивать нельзя. Multi-AZ выделяет синхронную standby-реплику в другой Availability Zone; каждый commit реплицируется на неё до подтверждения. Если primary падает, RDS автоматически переключает DNS-запись на standby, обычно в диапазоне 60–120 секунд. Но AWS прямо говорит: развёртывание Multi-AZ с одним standby «не является решением для масштабирования сценариев только-для-чтения. Нельзя использовать standby-реплику для обслуживания трафика чтения». Это высокая доступность, а не масштабирование чтения. Чтобы масштабировать чтение, добавляют read replicas: они реплицируются асинхронно (поэтому могут отставать), ты направляешь трафик чтения на их собственные эндпоинты, и — что важно — read replica может быть повышена (promote) до самостоятельного primary, частый путь для миграций и региональной DR.

# Multi-AZ = HA: синхронный standby, который НЕ обслуживает чтение
aws rds create-db-instance \
  --db-instance-identifier orders-primary \
  --engine postgres \
  --db-instance-class db.r6g.xlarge \
  --multi-az                      # автоматический failover, ~60-120с, НЕ масштабатор чтения

# Read replica = масштабирование чтения: асинхронно, свой эндпоинт, promotable
aws rds create-db-instance-read-replica \
  --db-instance-identifier orders-replica-1 \
  --source-db-instance-identifier orders-primary

DynamoDB: serverless NoSQL, живущая и умирающая по ключу партиции

DynamoDB — полностью управляемое, serverless key-value и документное хранилище. Нет инстансов, которые надо подбирать по размеру — ты отдаёшь AWS таблицу и паттерны доступа. У каждого элемента есть partition key (ключ партиции); DynamoDB прогоняет этот ключ через внутреннюю хеш-функцию, и выход выбирает физическую партицию, в которой живёт элемент. Опциональный sort key упорядочивает элементы с одним ключом партиции, давая range-запросы внутри одной коллекции. Сделанное верно, это даёт латентность в single-digit-миллисекунды на практически любом масштабе, потому что запрос резолвится в одну партицию хешированием, а не сканом.

Ты выбираешь режим ёмкости. On-demand тарифицирует за запрос и автомасштабируется мгновенно — идеально для непредсказуемого или всплескового трафика. Provisioned заставляет объявить read capacity units (RCU) и write capacity units (WCU), опционально с auto scaling. Один WCU — это запись 1 КБ/с; один RCU — strongly-consistent чтение 4 КБ в секунду (или два eventually-consistent чтения). Для более богатого доступа добавляют GSI (global secondary index) — другой ключ партиции, реплицированный и eventually consistent — или LSI (local secondary index), альтернативный sort key на том же ключе партиции.

Вот ловушка, которая троттлит команды, думающие, что у них есть запас: hot partition (горячая партиция). AWS проектирует каждую партицию выдавать максимум 3000 read units/сек и 1000 write units/сек. Если одно значение ключа партиции бьётся непропорционально — звёздный пользователь, enum status = "PENDING", сегодняшняя дата как ключ — весь этот трафик ложится на одну партицию, упирается в этот per-partition потолок, и тебя троттлит, хотя суммарная provisioned-ёмкость таблицы едва задействована. Вся игра в том, чтобы проектировать ключи с высокой кардинальностью, чтобы нагрузка расходилась равномерно; для неизбежно горячих ключей делают write-sharding, добавляя суффикс к ключу. И у DynamoDB нет джойнов и нет ad-hoc запросов — ты моделируешь под известные паттерны доступа заранее, часто через single-table design, и выбираешь eventual vs strong consistency на каждое чтение.

// Один элемент, смоделированный для доступа по пользователю, затем по недавнему заказу (sort key)
{
  "PK": { "S": "USER#42" },          // ключ партиции: высокая кардинальность, расходит нагрузку
  "SK": { "S": "ORDER#2026-06-04" }, // sort key: range-запросы внутри пользователя
  "total": { "N": "129.00" },
  "status": { "S": "PENDING" }       // НЕ делай это ключом партиции: hot partition
}
ИзмерениеRDS / Aurora (реляционная)DynamoDB (NoSQL)
Модель запросовSQL: джойны, ad-hoc запросы, транзакцииПо ключу; модель под паттерны доступа, без джойнов
МасштабированиеВертикальное (больше инстанс) + read replicas; есть потолокГоризонтальное по партициям; практически неограниченное
Высокая доступностьMulti-AZ синхронный standby, failover ~60–120сВстроенная; реплицируется по 3 AZ автоматически
Латентность на масштабеЗависит от индексов/тюнинга; деградирует под нагрузкойSingle-digit ms, если ключи расходятся равномерно
Классический режим отказаУпор в вертикальный потолок; допущение, что Multi-AZ масштабирует чтениеТроттлинг hot partition; нужен джойн, который не сделать
Почему это работает

Почему hot partition троттлит тебя, когда дашборд показывает свободную ёмкость? Per-partition лимиты DynamoDB (3000 RCU/сек, 1000 WCU/сек) физические, а не логические. Суммарная ёмкость таблицы делится между партициями, поэтому 100 000 provisioned WCU, размазанные по многим партициям, бесполезны единственному ключу, который маппится в одну партицию — этот ключ всё равно упирается в 1000 WCU/сек, а остальное уходит в троттлинг. Adaptive capacity может одолжить горячей партиции часть неиспользованной пропускной способности соседей, что смягчает, но не стирает лимит. Единственный надёжный фикс — дизайн ключа: расходи записи так, чтобы ни одна физическая партиция не была бутылочным горлышком.

Решение: богатые запросы против простого огромного масштаба

Правило, которое несут сеньоры: реляционная с богатыми запросами, транзакциями, джойнами и умеренным масштабом → RDS/Aurora; огромный масштаб, простой доступ по ключу, предсказуемая латентность и serverless-операции → DynamoDB. Тарификация обоих иллюстративна и зависит от региона — сверяй текущие ставки на страницах RDS pricing и DynamoDB pricing — но форма различается: RDS тарифицирует за инстанс-час плюс хранение независимо от загрузки; DynamoDB on-demand тарифицирует за запрос и реально падает к нулю в простое.

Классическая катастрофа lift-and-shift — взять нормализованную реляционную схему, скопировать её таблица-в-таблицу на DynamoDB «ради масштаба», а потом обнаружить, что приложению нужен джойн, который DynamoDB сделать не может — вынуждая N round-trip или скан, убивающий весь смысл. Моделируй паттерны доступа сначала; если им нужны ad-hoc джойны, тебе была нужна реляционная база.

Выбери лучший вариант

Хранилище состояния сессий многопользовательской игры: сотни тысяч записей/сек на пике, доступ только по ключу sessionId, нужна предсказуемая низкая латентность, и команда хочет ноль серверов БД в эксплуатации. Выбери базу.

Викторина

Ты включаешь RDS Multi-AZ и ждёшь, что read-heavy трафик ускорится. Не ускоряется. Почему?

Викторина

Твоя таблица DynamoDB provisioned с кучей суммарной ёмкости, но один паттерн доступа по ключу status постоянно троттлится. Что происходит?

Вспомните перед уходом
  1. 01
    Сопоставь RDS Multi-AZ с read replicas и скажи, чем RDS управляет за тебя, а чем нет.
  2. 02
    Объясни модель партиций DynamoDB и ловушку hot partition, и когда выбирать DynamoDB вместо RDS.
Итог

Управляемые базы данных в AWS делятся на две семьи. RDS и Aurora — управляемая реляционная: AWS владеет патчингом, бэкапами и failover, и ты получаешь SQL с джойнами, транзакциями и ad-hoc запросами — но ты по-прежнему владеешь схемой, индексами и тюнингом запросов и масштабируешься вертикально в жёсткий потолок. Две фичи RDS постоянно путают: Multi-AZ — синхронный standby в другой AZ, делающий failover автоматически примерно за 60–120 секунд и не обслуживающий чтение (высокая доступность, а не масштабирование чтения), тогда как read replicas асинхронны, имеют собственные эндпоинты для поглощения нагрузки чтения и могут быть повышены до primary. DynamoDB — serverless NoSQL: ключ партиции хешируется для выбора физической партиции, опциональный sort key упорядочивает элементы внутри неё, и ты получаешь латентность в single-digit-миллисекунды на любом масштабе — при условии, что ключи расходятся равномерно. Каждая партиция упирается примерно в 3000 read units и 1000 write units в секунду, поэтому низкокардинальный ключ порождает hot partition, который троттлит тебя при простаивающей суммарной ёмкости; лекарство — высококардинальные ключи или write-sharding. У DynamoDB нет джойнов, поэтому ты моделируешь под паттерны доступа заранее. Решение — это весь урок: богатые запросы, транзакции и джойны на умеренном масштабе хотят RDS/Aurora; огромный масштаб, простой доступ по ключу, предсказуемая латентность и ноль серверов в эксплуатации хотят DynamoDB. Цены иллюстративны и зависят от региона — всегда сверяй на страницах тарификации RDS и DynamoDB. Теперь, когда на ревью встретишь выбор базы, задай два вопроса: требует ли паттерн доступа джойнов или ad-hoc запросов — и если выбор пал на DynamoDB, какова кардинальность ключа партиции, потому что именно этот атрибут решит, получишь ли ты single-digit-ms или шторм троттлинга.

Практика

Начни сверху. Задачи идут от простого к сложному: вспомнить факт, применить к случаю, затем senior-уровень. Открой, попробуй, потом открой ответ.

вспомнитьприменитьуглубить0 из 5 завершено

Что-то непонятно?

Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.

Примени это

Примени этот урок в реальном проекте.

хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources2
expand
  1. 01
  2. 02

Trademarks belong to their respective owners. Editorial reference only.