Данные и базы

5 мин чтения·Опубликовано ·Обновлено

Репликация базы данных: зачем бизнесу несколько копий одних и тех же данных

Дополнительная копия помогает разгрузить чтение или пережить отказ сервера. Но для этих задач нужны разные настройки, а от ошибочного удаления данных реплика не спасает.

На вопрос о надёжности базы команда отвечает: «У нас есть реплика». Для руководителя это может означать, что при аварии работа продолжится. Для разработчика — что отчёты читают данные с другого сервера. Оба говорят об одной инфраструктуре, но обещают совершенно разный результат.

Репликация переносит изменения между копиями данных. Ниже речь о распространённой схеме: основной сервер принимает запись, дополнительные получают изменения. Существуют и другие модели, включая несколько узлов записи; их конфликты здесь не рассматриваем. Уже в простой схеме нужно разделить три задачи: разгрузить чтение, переключиться после отказа и восстановиться после неправильного изменения.

Отчётная база не обязательно готова заменить основную

Копия для чтения позволяет перенести часть запросов с основного сервера. Например, сотрудникам нужен тяжёлый отчёт, который мешает рабочим операциям. Если небольшая задержка данных допустима, такой запрос можно выполнять отдельно.

Но сама реплика тоже применяет изменения, поступающие с основного сервера. При нехватке ресурсов она начинает отставать. Дополнительные копии не увеличивают автоматически скорость записи в основном узле и не отменяют необходимость разбираться с тяжёлыми запросами.

Для аварийного резерва требования другие. Он должен иметь достаточно актуальные данные и мощность для рабочей нагрузки, подходящие настройки и готовый путь подключения приложений. Копия, которую нагрузили отчётами до предела, не обязательно соответствует этим требованиям. Это следует проверить, а не предполагать по её названию.

Подтверждённая запись может не попасть в резерв

При асинхронной репликации основной сервер способен подтвердить изменение раньше, чем оно окажется на дополнительном. Если основной узел безвозвратно потерян, последняя подтверждённая операция может отсутствовать у нового основного сервера. Этот риск описан, например, в документации PostgreSQL по репликации.

Для бизнеса вопрос звучит неприятнее, чем «какой у нас lag»: готовы ли мы потерять изменения, о сохранении которых уже сообщили пользователю? Если нет, нужны соответствующая схема подтверждения и разбор отказов, от которых она защищает. Сам факт существования второй машины ничего не обещает.

Синхронная репликация позволяет ждать подтверждения от выбранных резервных узлов. При этом увеличивается время записи и появляется зависимость от их доступности. Важен и смысл подтверждения: данные получены, записаны на устойчивый носитель или уже применены для чтения? Это разные гарантии. Слово «синхронная» без настроек не означает, что любая копия немедленно покажет новое состояние.

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

После изменения пользователь хочет увидеть результат

Сотрудник исправил реквизиты клиента. Запись ушла в основной узел, следующий экран прочитал отстающую реплику и показал старое значение. Человек решает, что сохранение не сработало, и повторяет действие. Инфраструктура работает по настройкам, а интерфейс сообщает пользователю не то, что он ожидает.

Такие маршруты чтения нужно проектировать отдельно. После записи можно обращаться к основному узлу или ждать, пока конкретная копия применит нужное изменение. Для отчёта иногда достаточно явно показать момент актуальности. Выбор зависит от операции, а не только от желания равномерно распределить запросы.

Даже чтение с основного узла не исправит ошибочные правила конкурентного изменения данных. Репликация и изоляция транзакций отвечают на разные вопросы. Удобство отображения также не заменяет проверку состояния перед финансово или операционно значимым действием.

В мониторинге полезно различать изменения, которые реплика ещё не получила, и изменения, которые получила, но не применила. Это разные причины отставания и разные действия для команды. Внешний признак «соединение установлено» не отвечает ни на один из этих вопросов. Для проверки пригодности резерва нужны также нагрузка, свободные ресурсы и состояние хранения.

Расположение копий тоже имеет значение. Два сервера, зависящие от одного питания, сети или другой общей инфраструктуры, не защищают от отказа этой общей части. Обсуждать нужно конкретную аварию, которую система обязана пережить.

Переключение — отдельная процедура

Обнаружить потерю связи ещё не значит доказать, что основной сервер выключен. При сетевом разрыве он может продолжать работать. Если одновременно разрешить запись на резервном, две стороны начнут принимать несовместимые изменения. Поэтому процедуре переключения нужна защита от одновременной работы двух основных узлов.

Далее необходимо выбрать пригодную копию, перевести приложения на новый адрес, восстановить соединения и разобраться с запросами, результат которых неизвестен. Таймаут во время аварии не доказывает, что запись не состоялась. Для повторов значимых операций нужна идемпотентность.

В описании failover PostgreSQL отдельно разбирается возвращение прежнего основного сервера. В управляемом сервисе часть действий выполнит поставщик, но приложение всё равно должно корректно пережить разрыв соединений и смену узла.

Ошибку удаления копия воспроизведёт тоже

Если приложение ошибочно удалило данные, обычная актуальная реплика применит это удаление. Для неё это такое же изменение, как правильное. Поэтому реплика не заменяет независимые резервные копии и восстановление к выбранному моменту.

Нужны отдельные правила хранения, доступ к резервам и проверка восстановления. Общие полномочия, позволяющие удалить одновременно рабочие данные и все резервные копии, оставляют неприятный общий риск. О механике восстановления по архиву журнала можно прочитать в документации PostgreSQL.

При приёмке полезнее попросить показать контролируемое переключение и отдельное восстановление ошибочно удалённых данных, чем считать серверы на схеме. Проверять следует вместе с приложением: продолжилась ли работа, какие подтверждённые операции сохранились, сколько заняли действия дежурного.

После удачного переключения бывшая реплика уже обслуживает продукт. Если другой резерв не создан, система снова осталась без дополнительной защиты. Поэтому в плане аварии должен быть не только момент «пользователи заработали», но и ответственный за восстановление резервирования.