Репликация: когда теория сталкивается с продакшеном

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


Проблема, которую решает репликация

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

Репликация решает сразу несколько проблем:

  1. Разгрузка основного узла — перенаправляем чтение на реплики, освобождая мастер для записи.
  2. Высокая доступность (HA) — если основной узел падает, реплика может подняться на его место (если настроена правильно).
  3. Бэкапы и аналитика — реплики можно использовать для резервного копирования или для запуска аналитических запросов без риска затормозить основную БД.
  4. Изоляция окружений — разработчики и тестировщики получают свои копии данных, не трогая продакшен.

Но! Репликация — это не волшебная палочка. Если её настроить неправильно, она может:

  • Увеличить latency между мастером и репликами.
  • Создать конфликты данных при конкурентных записях.
  • Стать причиной неожиданных отказов при сбоях сети.

Как это работает на самом деле

Репликация бывает синхронной и асинхронной. Выбор зависит от ваших требований к Consistency и Performance.

Синхронная репликация

Все записи сначала записываются на мастер, затем на реплики, и только после подтверждения от всех узлов — возвращается ответ клиенту.

Плюсы:

  • Гарантированная целостность данных.
  • Быстрое восстановление после сбоя (если реплика готова к промоушену).

Минусы:

  • Высокая нагрузка на сеть и узлы.
  • Возможны задержки (latency) при записи.

Пример конфига PostgreSQL (синхронная репликация):

# postgresql.conf (мастер)
synchronous_commit = on
synchronous_standby_names = 'standby1,standby2'
wal_level = replica
max_wal_senders = 3
wal_keep_size = 1GB

# pg_hba.conf
host replication repluser standby1_ip/32 md5
host replication repluser standby2_ip/32 md5

Асинхронная репликация

Записи идут на мастер, а реплики синхронизируются в фоновом режиме. Клиент получает ответ сразу после записи на мастер.

Плюсы:

  • Низкая нагрузка на сеть и узлы.
  • Быстрая запись данных.

Минусы:

  • Риск потери данных при сбое мастера (если реплики не успевают синхронизироваться).
  • Возможны расхождения между мастером и репликами.

Пример конфига MySQL (асинхронная репликация):

-- На мастере:
CHANGE MASTER TO
  MASTER_HOST='master_ip',
  MASTER_USER='repl_user',
  MASTER_PASSWORD='password',
  MASTER_LOG_FILE='mysql-bin.000003',
  MASTER_LOG_POS=107;

-- На реплике:
STOP SLAVE;
CHANGE MASTER TO
  MASTER_HOST='master_ip',
  MASTER_USER='repl_user',
  MASTER_PASSWORD='password',
  MASTER_LOG_FILE='mysql-bin.000003',
  MASTER_LOG_POS=107;
START SLAVE;

Типичные ошибки и как их избежать

  1. Неправильная настройка приоритетов реплик

    • Проблема: Если у вас несколько реплик, и одна из них отстаёт, а вы не настроили приоритеты, при падении мастера может подняться устаревшая реплика.
    • Решение: Используйте механизмы типа pg_controldata (PostgreSQL) или SHOW SLAVE STATUS (MySQL) для мониторинга отставания. Настраивайте приоритеты в кластере (например, через pg_auto_failover или Orchestrator).
  2. Отсутствие мониторинга отставания реплик

    • Проблема: Реплика отстаёт на часы, а вы об этом не знаете, пока не происходит сбой.
    • Решение: Настраивайте алерты на отставание реплик. Например, в PostgreSQL можно использовать расширение pg_stat_replication:
      SELECT * FROM pg_stat_replication;
      
      В MySQL — проверять Seconds_Behind_Master.
  3. Игнорирование сетевых проблем

    • Проблема: Репликация зависит от сети. Если между мастером и репликой плохой канал, данные будут теряться или дублироваться.
    • Решение: Используйте стабильные сети (например, dedicated links) и настраивайте timeout для репликации:
      # PostgreSQL
      hot_standby_feedback = on
      max_standby_archive_delay = 30s
      max_standby_streaming_delay = 30s
      
  4. Неправильная настройка WAL/redo-log

    • Проблема: Если логи репликации не сохраняются достаточно долго, реплика может потерять данные при сбое.
    • Решение: Настраивайте параметры сохранения логов:
      # PostgreSQL
      wal_keep_size = 1GB  # Сохранять логи не менее 1GB
      
  5. Забывание про транзакции при репликации

    • Проблема: Если вы выполняете длинные транзакции на мастере, реплики будут отставать.
    • Решение: Делите транзакции на более мелкие или увеличивайте ресурсы реплик.

Практический пример: развёртывание реплики PostgreSQL

Допустим, у вас есть мастер на db-master.example.com, и вы хотите добавить реплику на db-replica.example.com.

Шаг 1: Настройка мастера

  1. Редактируем postgresql.conf:
    wal_level = replica
    max_wal_senders = 3
    wal_keep_size = 1GB
    
  2. Редактируем pg_hba.conf для разрешения репликации:
    host replication repluser db-replica.example.com/32 md5
    
  3. Перезапускаем PostgreSQL:
    sudo systemctl restart postgresql
    

Шаг 2: Настройка реплики

  1. Клонируем мастер на реплику (метод pg_basebackup):

    pg_basebackup -h db-master.example.com -D /var/lib/postgresql/data -U repluser -P -v -Xs -R
    

    (Вводим пароль для пользователя repluser при запросе.)

  2. Редактируем postgresql.conf на реплике:

    hot_standby = on
    primary_conninfo = 'host=db-master.example.com port=5432 user=repluser password=password'
    
  3. Запускаем реплику:

    sudo systemctl start postgresql
    
  4. Проверяем статус репликации:

    SELECT * FROM pg_stat_replication;
    

Когда репликация не поможет

Репликация — это не панацея. Она не спасёт вас от:

  • Плохо написанных запросов — если ваши запросы на мастере уже тормозят систему, реплики это не исправят.
  • Конфликтов данных — если у вас распределённые транзакции или сложные схемы конкурентного доступа, репликация может усугубить проблемы.
  • Неправильной архитектуры — если вы пытаетесь реплицировать неоптимизированную БД с миллионами записей в таблице без индексов, ожидайте проблем.

Вывод: как правильно использовать репликацию

  1. Начинайте с асинхронной репликации, если вам нужна высокая производительность записи. Переходите на синхронную только если требуется строгая Consistency.
  2. Мониторьте отставание реплик — без этого вы рискуете потерять данные или получить устаревшую информацию.
  3. Тестируйте failover — регулярно проверяйте, как ваша система ведёт себя при сбое мастера.
  4. Не забывайте про сеть — репликация чувствительна к задержкам и потере пакетов.
  5. Документируйте конфигурацию — чтобы новая команда могла быстро разобраться, как всё работает.

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