Как происходит перенос данных на вторую ноду и насколько это сложно?
Что проверяют
Понимаете ли вы разницу между «добавить реплику» и «разнести данные по шардам» и представляете ли, что в этот момент происходит с приложением. Следом обычно спрашивают, как переключить трафик без простоя и что будет с запросом, который попал на отстающую реплику.
Как отвечать
Сначала уточните сценарий, сложность зависит от него:
- реплика для чтения или резерва: в PostgreSQL новая нода поднимается через
pg_basebackupсо снимка мастера и догоняет изменения потоковой репликацией по WAL. Это штатная операция, трудность только в объёме данных и нагрузке на диск и сеть во время копирования; - асинхронная или синхронная: по умолчанию репликация асинхронная, мастер не ждёт реплику, и при аварии последние транзакции можно потерять. Синхронный режим (
synchronous_standby_names) их сохраняет ценой задержки каждой записи; - логическая репликация:
PUBLICATIONиSUBSCRIPTIONпереносят отдельные таблицы и позволяют переехать между мажорными версиями почти без простоя; - шардирование: данные делятся по ключу между нодами. Вот это действительно сложно: нужен ключ шардирования, фоновое копирование с догонкой или двойная запись, сверка и переключение маршрутизации.
Покажите, что меняется и Python-код. В Django чтение уводят на реплику через DATABASE_ROUTERS, в SQLAlchemy через несколько движков и выбор сессии. Из-за лага реплики пользователь может не увидеть только что сохранённую запись, поэтому чтение сразу после записи отправляют на мастер.
Закончите планом переключения: копия, догонка, проверка лага и контрольных сумм, короткое окно только на чтение, смена адреса подключения, готовый план отката.
Где спотыкаются
Предлагают скопировать rsync каталог данных работающей базы. Без остановки сервера или штатного механизма резервного копирования получится несогласованная копия.
Не упоминают лаг реплики: приложение пишет в мастер, тут же читает с реплики и получает старые данные.
Путают реплику и шард. Реплика масштабирует чтение и даёт отказоустойчивость, но не делит нагрузку на запись, для этого нужно шардирование со всей его сложностью.