Ответ
Репликация данных — это процесс автоматического копирования и поддержания согласованности данных между несколькими экземплярами базы данных (репликами). Основные цели: повышение доступности, отказоустойчивость, масштабирование чтения и географическое распределение.
Основные модели репликации
1. Master-Slave (Primary-Replica)
- Master (Primary): Единственный узел, принимающий операции записи (INSERT, UPDATE, DELETE).
- Slave (Replica, Read-Replica): Узлы, которые получают копию данных с мастера и обслуживают только запросы на чтение.
Как работает: Изменения с мастера асинхронно (или синхронно) передаются на реплики через бинарный лог (binlog) или WAL (Write-Ahead Log).
Преимущества:
- Масштабирование чтения: Нагрузку
SELECTможно распределить по многим репликам. - Резервирование: При падении мастера одна из реплик может быть повышена до новой первичной.
- Аналитика: Запросы для отчетов можно выполнять на реплике, не нагружая мастер.
Пример конфигурации чтения/записи в Spring Boot:
@Configuration
public class DatabaseConfig {
// Бин для MASTER (запись)
@Bean
@Primary
@ConfigurationProperties("spring.datasource.master")
public DataSource masterDataSource() {
return DataSourceBuilder.create().build();
}
// Бин для SLAVE (чтение)
@Bean
@ConfigurationProperties("spring.datasource.slave")
public DataSource slaveDataSource() {
return DataSourceBuilder.create().build();
}
// Динамический маршрутизатор данных
@Bean
public DataSource routingDataSource(
@Qualifier("masterDataSource") DataSource master,
@Qualifier("slaveDataSource") DataSource slave) {
AbstractRoutingDataSource router = new AbstractRoutingDataSource() {
@Override
protected Object determineCurrentLookupKey() {
// Ключ определяется контекстом (например, аннотацией @Transactional)
return TransactionSynchronizationManager.isCurrentTransactionReadOnly()
? "slave"
: "master";
}
};
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put("master", master);
targetDataSources.put("slave", slave);
router.setTargetDataSources(targetDataSources);
router.setDefaultTargetDataSource(master); // По умолчанию мастер
return router;
}
}
// Сервис использует маршрутизацию автоматически
@Service
public class UserService {
@Transactional // Будет использовать master
public User createUser(User user) {
return userRepository.save(user); // Запись идет на мастер
}
@Transactional(readOnly = true) // Будет использовать slave
public User getUser(Long id) {
return userRepository.findById(id).orElse(null); // Чтение идет на реплику
}
}
2. Master-Master (Multi-Primary)
- Несколько мастеров, каждый может принимать запись.
- Изменения реплицируются между всмастерами.
- Сложность: Высокий риск конфликтов при одновременном изменении одних данных в разных мастерах. Требуются механизмы разрешения конфликтов.
- Применение: Географическое распределение для уменьшения задержки записи.
3. Шардирование (Сегментирование)
- Горизонтальное разделение данных: Разные строки одной таблицы хранятся на разных узлах (шардах) по определенному ключу (например,
user_id). - Решает проблему масштабирования записи.
- Часто комбинируется с репликацией: каждый шард может иметь свои реплики.
Синхронная vs Асинхронная репликация
- Синхронная: Мастер ждет подтверждения записи от реплик, прежде чем подтвердить транзакцию клиенту. Гарантирует полную согласованность, но снижает производительность и доступность (при падении реплики мастер может «зависнуть»).
- Асинхронная: Мастер подтверждает запись клиенту сразу, а репликация происходит «в фоне». Выше производительность и доступность, но возможна временная несогласованность (replica lag).
Итог: Репликация — ключевой механизм для построения надежных, производительных и отказоустойчивых систем хранения данных.