← Назад к вопросам
Что такое асинхронная репликация?
3.0 Senior🔥 141 комментариев
#DevOps и инфраструктура#Базы данных (SQL)
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# Асинхронная репликация: концепция и реализация
Асинхронная репликация — это процесс копирования данных с основного (master) сервера базы данных на один или несколько вспомогательных (slave/replica) серверов с задержкой. Основной сервер не ждет подтверждения репликации.
1. Как работает асинхронная репликация
Мастер (Master) Слейв (Slave)
┌─────────────────┐ ┌─────────────────┐
│ Клиент пишет │ │ │
│ данные │ │ │
└────────┬────────┘ └────────┬────────┘
│ │
├─ Записывает в Binary Log │
│ (WAL - Write Ahead Log) │
│ │
├─ COMMIT возвращается клиенту │
│ (он не знает о репликации) │
│ │
├──────────────────────────────────→│
│ Отправляет изменения асинхронно │
│ │
│ ┌────────────┤
│ │ Применяет │
│ │ изменения │
│ │ позже │
│ └────────────┘
2. Синхронная vs Асинхронная репликация
Синхронная репликация
Мастер ──запись──→ Слейв
↑ ↓
└────ДА/НЕТ────┘
Мастер ждет!
Плюсы:
- Данные гарантированно на всех серверах
- Нет потери данных при сбое
Минусы:
- Медленнее (зависит от сетевой задержки)
- Сбой слейва блокирует мастер
Асинхронная репликация
Мастер ──запись──→ Слейв
│ ↓
└─COMMIT──→ Клиент
(слейв обновляется позже)
Плюсы:
- Быстрее (не ждём подтверждения)
- Сбой слейва не влияет на мастер
- Масштабируемость
Минусы:
- Возможна потеря данных при сбое мастера
- Слейв может быть "позади" мастера
3. Процесс репликации в MySQL/PostgreSQL
┌──────────────────────────────────────────────────┐
│ 1. Клиент делает INSERT/UPDATE/DELETE на мастере │
└────────────────┬─────────────────────────────────┘
│
┌────────────────▼─────────────────────────────────┐
│ 2. Запись в Binary Log (MySQL) или WAL (PG) │
│ Содержит все изменения для повтора │
└────────────────┬─────────────────────────────────┘
│
┌────────────────▼─────────────────────────────────┐
│ 3. COMMIT ✓ (клиент получает подтверждение) │
│ Мастер не ждет слейва! │
└────────────────┬─────────────────────────────────┘
│
┌────────────────▼─────────────────────────────────┐
│ 4. Binlog Dump Thread отправляет на слейв │
│ (асинхронно, в фоне) │
└────────────────┬─────────────────────────────────┘
│
┌────────────────▼─────────────────────────────────┐
│ 5. Слейв получает изменения │
│ (может быть задержка в миллисекунды/секунды) │
└────────────────┬─────────────────────────────────┘
│
┌────────────────▼─────────────────────────────────┐
│ 6. Слейв применяет изменения локально │
│ (Relay Log → SQL Thread → локальные таблицы) │
└──────────────────────────────────────────────────┘
4. Настройка репликации в MySQL
На мастере:
-- 1. Включаем binary logging
SHOW VARIABLES LIKE 'log_bin';
-- должно быть ON в my.cnf
-- 2. Создаем пользователя для репликации
CREATE USER 'replication'@'slave_ip' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE ON *.* TO 'replication'@'slave_ip';
FLUSH PRIVILEGES;
-- 3. Получаем текущее положение в логе
FLUSH TABLES WITH READ LOCK; -- Блокируем писи
SHOW MASTER STATUS; -- Запоминаем File и Position
UNLOCK TABLES;
-- 4. Снимаем бэкап
mysqldump -u root -p --all-databases --master-data > dump.sql
На слейве:
-- 1. Восстанавливаем данные
mysql -u root -p < dump.sql
-- 2. Настраиваем параметры слейва (в my.cnf)
-- [mysqld]
-- relay-log = mysql-relay-bin
-- relay-log-index = mysql-relay-bin.index
-- server-id = 2
-- 3. Подключаемся к мастеру
CHANGE MASTER TO
MASTER_HOST = 'master_ip',
MASTER_USER = 'replication',
MASTER_PASSWORD = 'password',
MASTER_LOG_FILE = 'mysql-bin.000001',
MASTER_LOG_POS = 154;
-- 4. Запускаем слейв
START SLAVE;
-- 5. Проверяем статус
SHOW SLAVE STATUS\G
-- Slave_IO_Running: Yes
-- Slave_SQL_Running: Yes
-- Seconds_Behind_Master: 0
5. PostgreSQL потоковая репликация
# На мастере (postgresql.conf)
wal_level = replica
max_wal_senders = 10
wal_keep_size = 1GB
# На слейве (recovery.conf)
standby_mode = on
primary_conninfo = 'host=master_ip user=postgres'
6. Проблемы асинхронной репликации
Проблема: Потеря данных при крахе мастера
# Мастер
INSERT INTO users VALUES (1, 'Alice'); # Успешно
COMMIT; # Возвращена клиенту
# Но слейв еще не получил это!
# Мастер падает до того как отправить на слейв
# Данные потеряны!
Решение: Включить semi-sync репликацию
-- На мастере (MySQL)
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
SET GLOBAL rpl_semi_sync_master_enabled = ON;
SET GLOBAL rpl_semi_sync_master_timeout = 10000;
-- На слейве
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
SET GLOBAL rpl_semi_sync_slave_enabled = ON;
7. Задержка репликации (Replication Lag)
-- Проверяем задержку на слейве
SHOW SLAVE STATUS;
-- Seconds_Behind_Master показывает задержку
-- Если > 0, значит есть отставание
SELECT TIMESTAMPDIFF(SECOND, ts, NOW()) as lag_seconds
FROM heartbeat_table;
8. Использование репликации в приложении
import MySQLdb
from contextlib import contextmanager
class DatabasePool:
def __init__(self):
self.master = MySQLdb.connect(host='master', user='root')
self.slaves = [
MySQLdb.connect(host='slave1', user='root'),
MySQLdb.connect(host='slave2', user='root'),
]
@contextmanager
def get_connection(self, read_only=False):
if read_only:
# Используем слейв для чтения
conn = random.choice(self.slaves)
else:
# Используем мастер для записи
conn = self.master
try:
yield conn
finally:
conn.close()
# Использование
db = DatabasePool()
# Запись на мастер
with db.get_connection(read_only=False) as conn:
cursor = conn.cursor()
cursor.execute("INSERT INTO users VALUES (%s, %s)", (1, 'Alice'))
conn.commit()
# Чтение со слейва
with db.get_connection(read_only=True) as conn:
cursor = conn.cursor()
cursor.execute("SELECT * FROM users")
print(cursor.fetchall())
Ключевые выводы:
- Асинхронная репликация — мастер не ждет подтверждения слейва
- Быстрее синхронной, но есть риск потери данных
- Используй для читаемых нагрузок (селекты на слейвах)
- Master-Slave архитектура — пишем на мастер, читаем со слейва
- Задержка репликации (lag) — всегда может быть
- Semi-sync репликация — компромисс между скоростью и надежностью
- Мониторь репликацию с помощью
SHOW SLAVE STATUS