Как реализована репликация таблиц
Что проверяют
Понимаете ли вы, как база копирует данные на реплики и что из этого следует для кода сервиса. Следом обычно спрашивают про лаг реплики: пользователь сохранил запись, обновил страницу и не видит её.
Как отвечать
Сразу разведите два уровня: репликацию делает СУБД, а не ваш Go-код, от сервиса требуется правильно с ней жить. На примере PostgreSQL:
- физическая (streaming): реплика получает WAL и применяет его на уровне блоков. Копируется весь кластер целиком, реплика доступна только на чтение, мажорные версии должны совпадать;
- логическая:
CREATE PUBLICATIONна источнике иCREATE SUBSCRIPTIONна приёмнике, можно выбрать отдельные таблицы. Подходит для переезда между мажорными версиями и частичной синхронизации, но DDL сама не переносит, схему на приёмнике создают отдельно; - синхронная и асинхронная: по умолчанию асинхронная, коммит не ждёт реплику, и при падении мастера последние транзакции можно потерять. Синхронная задаётся через
synchronous_standby_namesиsynchronous_commit: мастер ждёт подтверждения, и каждая запись дорожает на сетевой круг.
Если речь про ClickHouse, там репликация как раз потабличная: движок ReplicatedMergeTree координирует реплики через ClickHouse Keeper или ZooKeeper.
Со стороны Go-сервиса расскажите, что делаете вы: два пула pgxpool (запись на мастер, чтение с реплик), чтение только что записанных данных с мастера, мониторинг лага через pg_stat_replication. Если данные нужно доставить в другую систему, это уже CDC: Debezium или своя читалка логического слота на pglogrepl.
Где спотыкаются
Пишут цикл «прочитать всю таблицу и вставить в другую раз в пять секунд». Это не репликация: удаления теряются, консистентности нет, а на большой таблице такой цикл просто не успевает.
Считают, что синхронная репликация бесплатно даёт согласованное чтение. Мастер ждёт подтверждения записи, но без remote_apply реплика ещё может отдавать старые данные.
Забывают про лаг и отправляют чтение сразу после записи на реплику, а потом ищут баг в кеше.