Репликация баз данных

Материал из llmdocs — справочник разработчика
Портал: Базы данных
Репликация баз данных
Целиотказоустойчивость, масштабирование чтения, близость к пользователям, резервирование
Схемыс одним ведущим, с несколькими ведущими, без ведущего
Режимысинхронный, асинхронный, полусинхронный
Уровнифизическая (журнал WAL, страницы), логическая (изменения строк)
PostgreSQLпотоковая репликация (9.0, 2010), логическая (10, 2017)
Управление отказамиPatroni, Orchestrator, облачные сервисы

Репликация базы данных — поддержание копий одних и тех же данных на нескольких серверах. Сервер, принимающий изменения, называют ведущим (primary, leader; устаревшее — master), а серверы-копии — репликами (replica, follower, standby). Изменения ведущего непрерывно передаются репликам и применяются там.

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

Схемы репликации

Схема Как устроена Плюсы Минусы
Один ведущий все записи идут на ведущий, реплики только читают просто, нет конфликтов записи запись не масштабируется, переключение при отказе
Несколько ведущих запись принимают несколько узлов, обычно в разных дата-центрах запись локально в каждом регионе конфликты одновременных изменений
Без ведущего клиент пишет и читает с нескольких узлов по кворуму высокая доступность сложная согласованность

Схема с одним ведущим — стандарт для PostgreSQL, MySQL и большинства реляционных СУБД. Репликация без ведущего с кворумами записи и чтения описана в статье Amazon о Dynamo (2007) и используется в Cassandra и ScyllaDB.[5]

Синхронная и асинхронная

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

В PostgreSQL режим задаётся параметрами synchronous_standby_names и synchronous_commit, причём выбирать можно даже для отдельной транзакции.[1]

Физическая и логическая

  • Физическая (потоковая) репликация передаёт журнал упреждающей записи (WAL) — побайтовые изменения страниц. Реплика — точная копия всего кластера, той же мажорной версии СУБД. В PostgreSQL доступна с версии 9.0 (2010).
  • Логическая репликация передаёт изменения на уровне строк (вставка, обновление, удаление) для выбранных таблиц. Позволяет реплицировать часть данных, между разными мажорными версиями (для обновления почти без простоя) и в другие системы. В PostgreSQL — с версии 10 (2017) по модели публикаций и подписок.[2]

В MySQL изменения передаются через двоичный журнал (binlog) в построчном или операторном формате, с глобальными идентификаторами транзакций (GTID) для надёжного переключения.[3]

-- PostgreSQL: логическая репликация одной таблицы
-- на источнике
CREATE PUBLICATION orders_pub FOR TABLE orders;
-- на получателе
CREATE SUBSCRIPTION orders_sub
  CONNECTION 'host=primary dbname=shop user=replicator'
  PUBLICATION orders_pub;

Отставание реплик

При асинхронной репликации реплика отстаёт от ведущего — обычно на миллисекунды, но под нагрузкой или при долгих запросах на реплике — на секунды и минуты. Отсюда аномалии, с которыми сталкивается приложение:[4]

  • Чтение собственных записей. Пользователь сохранил профиль, страница перезагрузилась с реплики — и изменения «пропали». Решение: читать данные, которые пользователь только что менял, с ведущего.
  • Монотонность чтений. Последовательные запросы попадают на разные реплики и видят данные «то новее, то старее». Решение: привязать сессию к одной реплике.

Отставание нужно мониторить: в PostgreSQL — через представление pg_stat_replication на ведущем.

Переключение при отказе

Если ведущий вышел из строя, одну из реплик нужно повысить до ведущего и перенаправить на неё клиентов. Делать это вручную долго, а автоматически — рискованно: при сетевом разделении два узла могут одновременно счесть себя ведущими (split brain) и принять конфликтующие записи. Поэтому для автоматического переключения используют инструменты с консенсусом через etcd, Consul или ZooKeeper — например, Patroni для PostgreSQL — или управляемые облачные базы данных.[6]

Репликация — не резервная копия

Реплика мгновенно повторяет и ошибочные изменения: случайный DELETE без WHERE или повреждение данных приложением дойдут до всех копий за доли секунды. Защиту от этого дают только резервные копии с историей и восстановлением на момент времени (см. Бэкапы: правило 3-2-1). Отложенная реплика (с задержкой применения на несколько часов) — полезное, но не заменяющее бэкапы дополнение.

Репликация и шардирование

Репликация копирует все данные на несколько узлов и масштабирует чтение, но не объём записи и не размер данных на одном узле. Для этого данные делят на части — шарды, — каждая из которых обычно ещё и реплицируется. Компромиссы между согласованностью и доступностью в таких системах описывает CAP-теорема.

См. также

Источники

  1. PostgreSQL Documentation — High Availability, Load Balancing, and Replication
  2. PostgreSQL Documentation — Logical Replication
  3. MySQL — Replication
  4. M. Kleppmann — Designing Data-Intensive Applications
  5. G. DeCandia et al. — Dynamo: Amazon's Highly Available Key-value Store (SOSP 2007)
  6. Patroni — документация