Когда следует использовать master-slave в БД?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Когда использовать master-slave репликацию в БД
Мaster-slave (Primary-Replica) репликация — это архитектура, где главная БД (master) реплицируется на одну или несколько подчинённых (slave). Это критично для масштабируемости и надёжности.
Основной механизм
Мaster DB (Write)
↓
WAL (Write-Ahead Log)
↓
Slave 1 DB (Read)
Slave 2 DB (Read)
Slave 3 DB (Read)
Все записи идут в master, все чтения могут идти в slave.
Когда использовать
1. Высокие объёмы чтений
Если у вас 1000 чтений на 10 записей, один master удовлетворит потребности:
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
# Master для записей
master_engine = create_engine('postgresql://localhost/mydb')
# Slaves для чтений
read_engines = [
create_engine('postgresql://slave1/mydb'),
create_engine('postgresql://slave2/mydb'),
]
def get_user(user_id):
# Читаем со случайного slave
import random
engine = random.choice(read_engines)
session = sessionmaker(bind=engine)()
return session.query(User).filter_by(id=user_id).first()
def create_user(email):
# Пишем в master
session = sessionmaker(bind=master_engine)()
user = User(email=email)
session.add(user)
session.commit()
return user
2. Масштабирование под бэкапы и аналитику
# Slave используется для:
# - Полного бэкапа (без блокировки master)
# - Аналитических запросов (тяжелые SELECT)
# - Тестирования (копия production)
mysqldump --single-transaction \
--master-data=2 \
-u root -p database > backup.sql
3. Высокая доступность и failover
# Если master упадёт, promocе slave
# Используйте инструменты типа MySQL Orchestrator
import pymysql
def write_with_failover(query):
try:
master_conn = pymysql.connect('master_host')
master_conn.query(query)
except Exception as e:
print(f"Master failed: {e}")
# Промотируем slave
slave_conn = pymysql.connect('slave_host')
slave_conn.query("STOP SLAVE;")
slave_conn.query("RESET MASTER;")
# Теперь slave стал master
4. Геораспределённые системы
Мaster в EU, slaves в US, Asia:
User in US
↓
Read → Slave (US) ← Репликация ← Master (EU)
(2ms) (100ms)
Вместо:
Read → Master (EU) (100ms)
Когда НЕ использовать
1. Маленькие приложения
Оверхед на репликацию больше, чем выигрыш:
# Если вы имеете:
# - 100 пользователей
# - 1 запрос в минуту
# Репликация ненужна
2. Требования сильной консистентности
Eslave отстаёт на миллисекунды/секунды:
# ❌ ПЛОХО
user = create_user(email) # Пишем в master
user_data = get_user(user.id) # Читаем со slave
# user_data может быть None, если slave ещё не синхронизировался
# ✅ ХОРОШО
user = create_user(email) # Пишем в master
# Читаем из master на время
session = sessionmaker(bind=master_engine)()
user_data = session.query(User).filter_by(id=user.id).first()
3. Частые изменения схемы
Миграции нужно синхронизировать:
# На master
ALTER TABLE users ADD COLUMN age INT;
# Slave автоматически получит эту команду
# Но может отстать, если она тяжелая
Проблемы и решения
Проблема: Лаг репликации (Replication Lag)
# Slave отстаёт на 2 секунды
import time
def safe_read_after_write(user_id):
# Записываем в master
user = create_user(email)
# Ждём синхронизации
time.sleep(2)
# Читаем со slave
return get_user(user_id)
Или используйте read-after-write consistency:
def get_user_safe(user_id, master=False):
# Если нужна гарантия, читаем из master
if master:
engine = master_engine
else:
engine = random.choice(read_engines)
session = sessionmaker(bind=engine)()
return session.query(User).filter_by(id=user_id).first()
Проблема: Split Brain (два master)
# Сетевой раздел между master и slave
# Оба начинают принимать писки
# Данные расходятся
# Решение: использовать fencing
# Автоматически отключить старый master
PostgreSQL репликация
# На master (postgresql.conf)
wal_level = replica
max_wal_senders = 10
wal_keep_size = 1GB
# На slave
standby_mode = on
restore_command = 'cp /archive/%f %p'
# Проверка статуса
psql -c "SELECT * FROM pg_stat_replication;"
MySQL репликация
# На master
BINARY FORMAT = ROW
BINLOG_EXPIRE_LOGS_DAYS = 7
# На slave
CHANGE MASTER TO
MASTER_HOST = 'master_host',
MASTER_USER = 'replication_user',
MASTER_PASSWORD = 'password',
MASTER_LOG_FILE = 'mysql-bin.000001',
MASTER_LOG_POS = 154;
START SLAVE;
SHOW SLAVE STATUS;
Итоги
- Используйте master-slave, если читаете в 10+ раз больше, чем пишете
- Усложняет архитектуру — нужна обработка лага репликации
- Решает масштабирование под чтения
- Не решает масштабирование под записи (нужно sharding)
- Требует мониторинга — лаг, failover, консистентность