> Какие виды репликаций существуют (Go)
Уровень: senior · Роль: backend · Язык: Go · Категория: Технические вопросы
Компании: Employcity
Стек: Go
> Пример ответа
Короткий ответ
Репликация в базах данных бывает трёх основных видов: single-leader (master-slave), multi-leader и leaderless. В single-leader все записи идут через один узел, чтение - с реплик. В multi-leader несколько узлов принимают записи, что даёт лучшую доступность, но требует разрешения конфликтов. В leaderless (например, Dynamo-style) любой узел принимает записи, консистентность обеспечивается через quorum. Также различают синхронную и асинхронную репликацию, и по способу передачи - statement-based, WAL-based и row-based.
Подробное объяснение
Репликация решает три задачи: отказоустойчивость, масштабирование чтения и географическая распределённость. Основные модели:
Single-leader (master-slave)
- Один узел (leader) принимает все записи, остальные (followers) копируют изменения.
- Чтение можно масштабировать горизонтально, но запись ограничена одним узлом.
- Если leader падает, нужен failover - выбор нового лидера, что может привести к потере данных при асинхронной репликации.
Multi-leader
- Несколько лидеров принимают записи, каждый реплицирует свои изменения остальным.
- Используется в multi-datacenter сценариях, где важна локальная запись.
- Главная проблема - конфликты записи (например, два лидера обновили одну строку). Решения: last-write-wins, merge, CRDT.
Leaderless
- Любой узел принимает чтение и запись, консистентность через quorum (например, W + R > N).
- Примеры: Cassandra, Riak, DynamoDB.
- Хорошо переносит отказы узлов, но требует аккуратной настройки quorum и разрешения конфликтов на чтении (read repair, hinted handoff).
По синхронности
- Синхронная: leader ждёт подтверждения от реплики перед ответом клиенту. Гарантирует отсутствие потерь, но увеличивает задержку.
- Асинхронная: leader отвечает сразу, репликация идёт в фоне. Быстрее, но возможна потеря данных при сбое лидера.
- Semi-synchronous: компромисс - ждём подтверждения от одной реплики.
По механизму передачи
- Statement-based: передаются SQL-запросы. Просто, но недетерминированные функции (NOW(), RAND()) дают расхождения.
- WAL-based: передаётся write-ahead log. Надёжно, но привязывает к формату хранения.
- Row-based: передаются изменённые строки. Универсально, используется в MySQL binlog, PostgreSQL logical replication.
На практике
В Go-проектах репликация чаще всего настраивается на уровне БД, а не приложения. Но важно понимать, как она влияет на код:
- При использовании single-leader нужно разделять пулы соединений: записи - на leader, чтения - на followers. В Go это делается через отдельные
sql.DBили через middleware типаpgxс указанием роли. - Для чтения с реплик нужно учитывать репликационную задержку. Если пользователь только что записал данные и сразу читает, он может не увидеть их на follower. Решение - read-your-writes consistency: для критичных запросов читать с leader.
- В multi-leader сценариях в Go-приложении нужно обрабатывать конфликты на уровне бизнес-логики, например, через версионирование или CRDT.
- При использовании leaderless (например, Cassandra) в Go-драйвере настраивается consistency level:
QUORUM,ONE,LOCAL_QUORUM. Это влияет на задержку и консистентность.
Пример кода
Пример разделения чтения и записи в Go с PostgreSQL:
GOtype DB struct {write *sql.DBread *sql.DB}func NewDB(writeDSN, readDSN string) (*DB, error) {write, err := sql.Open("pgx", writeDSN)if err != nil {return nil, err}read, err := sql.Open("pgx", readDSN)if err != nil {return nil, err}return &DB{write: write, read: read}, nil}func (d *DB) CreateUser(ctx context.Context, u User) error {_, err := d.write.ExecContext(ctx, "INSERT INTO users (name) VALUES ($1)", u.Name)return err}func (d *DB) GetUser(ctx context.Context, id int, readYourWrites bool) (*User, error) {db := d.readif readYourWrites {db = d.write}row := db.QueryRowContext(ctx, "SELECT id, name FROM users WHERE id = $1", id)// ...}
Как отвечать на собеседовании
Начни с краткой классификации, затем углубляйся в зависимости от вопросов. Обязательно упомяни trade-off между консистентностью и доступностью, особенно в контексте CAP-теоремы. Приведи примеры из реальных систем: PostgreSQL (single-leader), MySQL Group Replication (multi-leader), Cassandra (leaderless). Покажи понимание, как репликация влияет на приложение: read-your-writes, задержки, обработка конфликтов. Если спросят про Go - расскажи про разделение пулов соединений и настройку драйверов.
Что проверяет интервьюер
- Понимание базовых моделей репликации и их отличий.
- Умение объяснить trade-off между синхронной и асинхронной репликацией.
- Знание механизмов разрешения конфликтов в multi-leader и leaderless.
- Понимание влияния репликации на проектирование приложения (консистентность чтения, задержки).
- Способность применить знания к конкретному стеку (Go, PostgreSQL, Cassandra).
Типичные ошибки
- Смешивание понятий "репликация" и "шардирование" - это разные вещи.
- Утверждение, что multi-leader всегда лучше single-leader - на самом деле он добавляет сложность с конфликтами.
- Игнорирование репликационной задержки при чтении с followers.
- Непонимание, что синхронная репликация не гарантирует отсутствие потерь при network partition.
- В Go-коде - использование одного пула соединений для чтения и записи без учёта роли узла.
> Похожие задачи по Go
Почему нельзя заменить WITH (CTE) на подзапрос в SQL
Что такое паттерн разделения на чтение и запись
Для чего лучше подходят синхронные и асинхронные репликации
Какие доводы и обстоятельства влияют на решение о делении или объединении сервисов
> Похожие задачи по backend
Почему нельзя заменить WITH (CTE) на подзапрос в SQL
Что такое паттерн разделения на чтение и запись
Для чего лучше подходят синхронные и асинхронные репликации
Какие доводы и обстоятельства влияют на решение о делении или объединении сервисов
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью