Для чего используются мастер и реплики (синхронная и асинхронная) в базе данных
Что проверяют
Понимаете ли вы, какую проблему решают реплики и чем приходится платить за синхронность. Бэкендеру на Go следом задают прикладной вопрос: что будет, если сразу после записи прочитать данные с реплики.
Как отвечать
Мастер (primary) принимает все записи. Реплики получают поток изменений: в PostgreSQL это WAL через streaming replication, в MySQL binlog. Зачем это нужно:
- отказоустойчивость: при падении мастера реплику повышают до мастера, вручную или через Patroni;
- масштабирование чтения: тяжёлые выборки, отчёты и аналитику уводят с мастера;
- обслуживание: бэкапы снимают с реплики, не нагружая мастер.
Разница режимов в том, когда мастер отвечает клиенту «записано»:
- асинхронная: сразу после локального коммита. Запись быстрая, но реплика отстаёт (replication lag), а при аварии мастера последние подтверждённые транзакции теряются;
- синхронная: только после подтверждения от синхронной реплики. Подтверждённая запись переживает отказ мастера, но каждая транзакция ждёт сетевого круга, а недоступность реплики блокирует коммиты.
В PostgreSQL глубину ожидания задаёт synchronous_commit: remote_write, on (реплика сбросила WAL на диск) или remote_apply (изменение уже видно запросам на реплике). Какие реплики синхронные, решает synchronous_standby_names, например ANY 1 (r1, r2) для кворума. В MySQL близкий аналог это полусинхронная репликация.
В коде на Go обычно держат два *sql.DB или два пула pgxpool: запись и чтение сразу после записи идут в мастер, остальное в реплики. Если в строке подключения pgx перечислено несколько хостов, target_session_attrs=read-write выберет тот, что принимает запись.
Где спотыкаются
Считают, что синхронная реплика всегда отдаёт свежие данные. В PostgreSQL это верно только для remote_apply: при on изменение уже на диске реплики, но запрос может его ещё не увидеть.
Говорят, что мастер ждёт подтверждения от всех реплик. Обычно ждут одну или кворум, иначе отказ любой реплики останавливает запись.
Называют реплику бэкапом. DELETE без WHERE доедет до реплики за миллисекунды, от ошибки человека спасают только бэкапы с восстановлением на момент времени (PITR).