Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
# Master-Slave репликация в базах данных
Master-Slave (или в современной терминологии Primary-Replica) — это паттерн репликации данных, при котором одна БД (Master) выступает источником истины, а другие (Slave) получают копию данных.
Основная архитектура
Master сервер обрабатывает все write операции. Slave серверы получают изменения через репликацию и обслуживают read операции.
Основные цели использования
1. Масштабируемость для чтения (Read Scaling)
Это главная цель Master-Slave. Когда возрастает нагрузка на чтение, распределяем её между несколькими серверами:
public class UserRepository {
private DataSource masterDataSource; // для WRITE
private DataSource[] slaveDataSources; // для READ
public User findById(UUID id) {
// Читаем с одного из slave серверов (round-robin)
DataSource slave = roundRobinSelect(slaveDataSources);
return queryWithConnection(slave,
"SELECT * FROM users WHERE id = ?", id);
}
public void save(User user) {
// Пишем только в master
return queryWithConnection(masterDataSource,
"INSERT INTO users ...");
}
}
Пример: Master обрабатывает 1000 write ops/sec, каждый Slave — 5000 read ops/sec. С тремя Slave можем обслужить 15,000 read ops/sec.
2. Высокая доступность (High Availability)
Если Master выходит из строя, один из Slave может быть пропагандирован в Master:
class HighAvailabilityDataSource {
private PrimaryDatabase master;
private List<ReplicaDatabase> slaves;
public synchronized void onMasterFailure() {
// Выбираем самый актуальный slave
ReplicaDatabase newMaster = slaves.stream()
.max(comparing(ReplicaDatabase::getReplicationLag))
.orElseThrow();
// Пропагандируем его в master
newMaster.promoteToPrimary();
// Обновляем конфиг
master = newMaster;
// Переприсоединяем других slaves к новому master
slaves.forEach(slave -> slave.setMaster(newMaster));
}
}
3. Data Backup и Archive
Slave можно использовать как резервную копию без потери основной БД. На slave можно делать backup без блокировки master, пока тот обслуживает пользователей.
4. Аналитика и Reporting
Если запускать heavy аналитические запросы на Master, они замедлят основное приложение. Используем Slave для этого:
public class UserService {
private DataSource masterDs; // для OLTP
private DataSource analyticsDs; // для OLAP
public User findById(UUID id) {
return query(masterDs, "SELECT * FROM users WHERE id = ?");
}
// Тяжёлые аналитические запросы на отдельном сервере
public List<UserStatistics> generateMonthlyReport() {
return query(analyticsDs,
"SELECT user_id, COUNT(*) as actions_count " +
"FROM user_actions WHERE date >= now() - interval 1 month " +
"GROUP BY user_id");
}
}
5. Test и Development
Можно использовать copy данных с Slave для тестирования без затрагивания production.
Как работает репликация
Master логирует все write операции в binary log. Slave подписывается на этот лог, получает команды и выполняет их локально.
Есть два подхода:
- Statement-based: логируют SQL команды. Проблема если есть NOW(), UUID() — результаты могут различаться.
- Row-based: логируют изменения по строкам. Современный подход, более надёжный.
Проблемы и решения
Replication Lag (задержка репликации)
Данные на Slave могут отставать на несколько секунд. Если сразу после INSERT читать с lag-ging Slave, можем не найти данные:
// Решение: Read From Master After Write
public void createAndGet(Comment comment) {
master.save(comment); // Пишем в master
return master.findById(comment.getId()); // Читаем из master
}
Write-Write Conflicts в Multi-Master
Если несколько Master серверов пишут одновременно — возникают конфликты. Поэтому используется один Master (классическая архитектура).
Когда использовать Master-Slave
- Нужно масштабировать read операции
- Требуется высокая доступность
- Нужна резервная копия без блокировки
- Есть heavy аналитические запросы
Альтернативы и расширения
- Шардирование: для масштабирования write операций
- Гибридный подход: Master-Slave + Sharding
- Read replicas в облаке: AWS RDS, Google Cloud SQL
Это проверенная временем паттерн, используемая в производстве везде.