Эталонная архитектура: трёхуровневое OLTP-приложение
Классические бизнес-приложения (заказы, платежи, склад) выполняют большое число коротких однострочных транзакций, критичных к согласованности (OLTP). Это дерево пошагово показывает, начиная с определения профиля нагрузки, когда вводить основную реляционную базу данных, пул соединений, реплики для чтения, уровень кэша, бэкап + PITR и мониторинг. Цель — не «добавить всё заранее», а добавлять нужный компонент по мере подтверждения каждого узкого места.
Каков профиль нагрузки: состав транзакций и требования к согласованности?
Первое решение в архитектуре OLTP — является ли нагрузка действительно транзакционной (короткая смесь записи и чтения, требующая ACID). Данные по своей природе реляционные и согласованность критична (деньги, остатки, заказы), нагрузка в основном на чтение, или нагрузка пока очень низкая?
- Короткие транзакции, строгая согласованность (деньги/остатки/заказы)
- Сильно преобладает чтение, мало записи, трафик растёт
- Нагрузка очень низкая; достаточно ли самой простой конфигурации?
Вы выбрали основную СУБД и беспокоитесь о масштабировании?
Реляционная СУБД — правильная основа для транзакционного ядра (PostgreSQL, MySQL/InnoDB, Oracle, SQL Server). Когда выбор СУБД ясен, следующий вопрос — масштабирование: пока достаточно одного экземпляра или растут число соединений и нагрузка чтения?
- СУБД выбрана; пока достаточно одного экземпляра
- Число соединений резко выросло, ресурсы заканчиваются
- Нагрузка чтения растёт и перегружает основной экземпляр записи
Как масштабировать чтение: реплика или кэш?
Если нагрузка чтения перегружает основной экземпляр, есть два взаимодополняющих варианта. Чтения, допускающие немного отстающие данные, такие как отчёты/списки, можно направить на реплику для чтения; если одни и те же «горячие» данные запрашиваются снова и снова, кэш с микросекундной задержкой (Redis) разгружает БД.
- Много чтений отчётов/списков; небольшая задержка допустима
- Одни и те же популярные данные читаются снова и снова
Рекомендация: начните с одного первичного сервера + пула + бэкапа
На раннем этапе держите архитектуру простой: достаточно одного реляционного первичного экземпляра, пула соединений перед ним и регулярных бэкапов. Добавляйте сложность, только когда этого требует измеренное узкое место.
Рекомендация: добавьте пул соединений
В OLTP, когда каждый экземпляр приложения открывает собственные соединения, основная БД задыхается от накладных расходов на память и планировщик при тысячах соединений. Пул между ними распределяет небольшое число реальных соединений с БД между множеством запросов приложения.
Рекомендация: добавьте реплику для чтения
Запись остаётся на первичном сервере, а трафик только для чтения (отчёты, списки, поиск) направляется на одну или несколько асинхронных реплик, получающих данные от первичного сервера. Это освобождает первичный сервер для записи и чтений, критичных к согласованности.
Рекомендация: добавьте уровень кэша (Redis)
Если одни и те же популярные данные (сессии, каталог, профили, фрагменты страниц) читаются многократно, поставьте кэш в памяти перед БД и обслуживайте большинство чтений, вообще не доходя до БД. Задержка снижается, а основная БД разгружается.