← Назад к вопросам

Как часто обновляется Slave БД в Master-Slave

1.8 Middle🔥 101 комментариев
#Базы данных и SQL

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как часто обновляется Slave БД в Master-Slave репликации

Очень важный вопрос о репликации данных. Частота обновления Slave БД зависит от нескольких факторов и отличается в зависимости от типа репликации.

Асинхронная репликация (по умолчанию)

В стандартной Master-Slave репликации используется асинхронный подход:

Как это работает:

  • Операция записи выполняется на Master БД
  • Master отправляет информацию об изменении в бинарный лог (binary log)
  • Slave подключается к Master через IO-thread и читает события из бинарного лога
  • SQL-thread на Slave воспроизводит эти события в том же порядке
  • Задержка между Master и Slave может составлять от миллисекунд до нескольких секунд

Основные особенности:

  • Нет гарантии, что данные на Slave синхронизированы к моменту чтения
  • Slave может отставать на N операций и на N миллисекунд
  • Если Slave упадет, неработанные данные из бинарного лога могут быть потеряны
  • Master не дожидается подтверждения от Slave перед завершением операции
// Пример: записываем данные на Master
JdbcTemplate masterTemplate = new JdbcTemplate(masterDataSource);
masterTemplate.update("INSERT INTO users (id, name, email) VALUES (?, ?, ?)", 
    userId, userName, userEmail);

// Slave может еще не иметь этих данных!
// Может быть задержка в несколько миллисекунд или секунд
Thread.sleep(100); // Приблизительная ожидаемая задержка

JdbcTemplate slaveTemplate = new JdbcTemplate(slaveDataSource);
User user = slaveTemplate.queryForObject("SELECT * FROM users WHERE id = ?", 
    new UserRowMapper(), userId);
// Может быть null если задержка репликации больше 100ms

Синхронная репликация (Semi-synchronous)

Можно настроить режим полусинхронной репликации:

Характеристики:

  • Master ждет подтверждения от хотя бы одного Slave перед завершением операции
  • Гарантирует, что данные дошли до Slave, но не гарантирует их обработку
  • Задержка рассчитывается на сеть и пропускную способность
  • Если Slave не отвечает в течение timeout (по умолчанию 10 сек), репликация переходит в асинхронный режим

Конфигурация в MySQL:

-- На Master
SET GLOBAL rpl_semi_sync_master_enabled = ON;
SET GLOBAL rpl_semi_sync_master_timeout = 10000; -- 10 секунд

-- На Slave
SET GLOBAL rpl_semi_sync_slave_enabled = ON;

Факторы, влияющие на задержку репликации

  1. Сетевая задержка — время передачи данных между Master и Slave

    • Обычно: 1-50 ms в одном дата-центре
    • Может быть: 100+ ms между разными регионами
  2. Объем данных — большие транзакции дольше реплицируются

    // Плохо: одна большая транзакция
    for (int i = 0; i < 1_000_000; i++) {
        insert("INSERT INTO logs (data) VALUES (?)", logData[i]);
    }
    // Задержка репликации может быть в минуты
    
    // Хорошо: батч-операции
    List<String> batch = new ArrayList<>();
    for (int i = 0; i < 1_000_000; i += 10_000) {
        // Групповая вставка 10k записей
        insertBatch(batch);
        batch.clear();
    }
    
  3. Нагрузка на Slave — если Slave перегружена обработкой предыдущих операций

    • Может отставать на часы, даже дни в экстремальных случаях
  4. Индексы и структура — сложные индексы замедляют воспроизведение операций

  5. Версии MySQL/PostgreSQL — разные версии имеют разные оптимизации

Мониторинг задержки репликации

-- На Slave: проверить статус репликации
SHOW SLAVE STATUS\G

-- Ключевые параметры:
-- Seconds_Behind_Master = текущая задержка в секундах
-- Slave_IO_Running = получение логов от Master
-- Slave_SQL_Running = применение логов на Slave
// В Java: проверить задержку программно
public class ReplicationLagMonitor {
    public int getReplicationLagSeconds(DataSource slaveDataSource) {
        String query = "SHOW SLAVE STATUS";
        // Парсим результат и извлекаем Seconds_Behind_Master
        // Возвращаем в секундах
    }
    
    public void ensureDataConsistency(DataSource slaveDataSource, 
                                      int maxLagSeconds) {
        int currentLag = getReplicationLagSeconds(slaveDataSource);
        if (currentLag > maxLagSeconds) {
            throw new ReplicationLagException(
                "Slave отстает на " + currentLag + " сек. Нужно максимум: " + maxLagSeconds);
        }
    }
}

Рекомендации для Java приложений

  1. Не полагайся на немедленную консистентность — при чтении с Slave используй кеш или жди задержку
  2. Используй Slave для чтения, Master для записи — паттерн CQRS
  3. Мониторь lag постоянно — создавай алерты при lag > 5 сек
  4. Для критичных данных читай с Master — это дороже, но гарантирует актуальность
  5. Батчь операции — уменьшает общий объем данных в логах
  6. Используй полусинхронную репликацию для критичных систем

Итог

В стандартной Master-Slave репликации Slave может обновляться с задержкой от миллисекунд до нескольких секунд (в нормальных условиях). При необходимости гарантированной консистентности используй синхронную или полусинхронную репликацию, хотя это снижает производительность.