Содержание
Масштабировать базу данных стоит по ступеням: сначала оптимизировать запросы и индексы, затем увеличить сервер, затем вынести чтение на реплики и только в крайнем случае разделить данные на шарды. Большинству продуктов хватает первых трёх шагов на годы вперёд, а шардирование резко усложняет разработку и эксплуатацию.
Разберём, как работает репликация, какие у неё подводные камни, что такое партиционирование и шардирование и когда к ним переходить.
Когда база данных становится узким местом?
База становится узким местом, когда растут время ответа запросов, загрузка процессора и диска сервера базы, а очередь соединений не успевает разбираться. Но прежде чем масштабировать, стоит проверить, не решается ли проблема дешевле.
Порядок действий:
- Оптимизация запросов. Медленные запросы без индексов, проблемы N+1 и лишние выборки — частая причина нагрузки; подробнее в статье индексы в PostgreSQL.
- Кеширование. Часто читаемые данные — в кеш, статья кеширование в веб-приложении.
- Пул соединений. Тысячи соединений от приложения перегружают базу сильнее, чем запросы.
- Вертикальное масштабирование. Больше процессоров, памяти и быстрые диски — самый простой шаг.
- Реплики для чтения. Когда большая часть нагрузки — чтение.
- Шардирование. Когда не справляется запись или данные не помещаются на один сервер.
Как работает репликация?
Репликация — это копирование изменений с основного сервера базы на один или несколько дополнительных. Основной сервер принимает запись, реплики получают поток изменений и применяют его у себя. Читать можно с реплик, разгружая основной сервер.
| Задача | Как помогает репликация |
|---|---|
| Нагрузка на чтение | Отчёты, каталоги и поиск читают с реплик |
| Отказоустойчивость | При падении основного сервера реплика становится основной |
| Аналитика | Тяжёлые запросы аналитиков не мешают пользователям |
| Обслуживание | Обновления проводят поочерёдно, без остановки |
Фото: Unsplash
Какие проблемы создаёт задержка репликации?
Реплика отстаёт от основного сервера на миллисекунды, а под нагрузкой — на секунды. Если пользователь сохранил профиль, а следующая страница читается с реплики, он может увидеть старые данные и решить, что сохранение не сработало.
Как с этим работать:
- после записи читайте данные того же пользователя с основного сервера в течение короткого времени;
- критичные проверки — остатки, балансы, права доступа — делайте только на основном сервере;
- следите за задержкой репликации и выводите отстающую реплику из работы;
- не используйте реплики внутри транзакций, которые потом пишут данные.
// Laravel: после записи в рамках запроса чтение идёт с основного сервера
'mysql' => [
'read' => ['host' => ['replica-1', 'replica-2']],
'write' => ['host' => ['primary']],
'sticky' => true,
],
Что такое партиционирование и шардирование?
Партиционирование делит большую таблицу на части внутри одного сервера — например, по месяцам. Шардирование распределяет данные по разным серверам — например, по идентификатору клиента. Партиционирование почти не усложняет приложение, шардирование — сильно.
Что усложняет шардирование:
- запросы и отчёты по всем данным нужно собирать с нескольких серверов;
- транзакции между шардами практически недоступны;
- перебалансировка данных при добавлении шарда — отдельный сложный проект;
- миграции схемы, бэкапы и мониторинг множатся по числу шардов.
Хорошее естественное разбиение — по клиенту в B2B SaaS: данные клиентов почти не пересекаются. Подробнее — в статье мультитенантность в SaaS.
Когда переходить к шардированию?
К шардированию переходят, когда один сервер не выдерживает нагрузку на запись даже после оптимизации и максимального вертикального масштабирования или когда объём данных не помещается на самый большой доступный сервер. Для большинства продуктов этот момент не наступает никогда.
Перед решением:
- соберите статистику: что именно нагружает базу — чтение или запись;
- проверьте, не помогут ли партиционирование и архивация старых данных;
- оцените, нельзя ли вынести аналитику в отдельное хранилище — статья ClickHouse для аналитики;
- выберите ключ шардирования, по которому почти все запросы попадают в один шард.
Коротко
- Масштабируйте по ступеням: запросы, кеш, сервер побольше, реплики, шарды.
- Реплики разгружают чтение и дают отказоустойчивость, но отстают от основного сервера.
- Критичные данные читайте с основного сервера, особенно сразу после записи.
- Партиционирование делит таблицу внутри сервера, шардирование — данные между серверами.
- Шардирование — крайняя мера, к которой большинству продуктов переходить не нужно.
Частые вопросы
Реплика заменяет резервную копию?
Нет. Реплика мгновенно повторяет все изменения, включая ошибочное удаление данных. Резервные копии нужны отдельно — они позволяют вернуться в момент до ошибки.
Сколько реплик нужно?
Для отказоустойчивости достаточно одной реплики в другой зоне доступности. Дополнительные реплики добавляют, когда нагрузку на чтение не выдерживает одна.
Шардирование можно включить без изменения кода?
Есть расширения и прокси, которые прячут шардирование от приложения, но запросы между шардами и транзакции всё равно ведут себя иначе. Почти всегда код и схему данных приходится адаптировать.



