Пользователь сохранил изменения, обновил страницу — а изменений нет. Что происходит и как это исправить?
- Что такое отставание реплики?
- Как обеспечить read-your-writes при чтении с реплик?
- Что такое монотонное чтение?
Запись ушла в лидера, а чтение — на асинхронную реплику, которая ещё не догнала. Это нормальное поведение асинхронной репликации; приложение должно давать нужные гарантии само.
- Read-your-writes: свои данные после записи читать с лидера (или с реплики, догнавшей нужную позицию)
- Монотонное чтение: привязать пользователя к одной реплике, чтобы не «откатываться назад» при обновлении
- Причинная согласованность: ответ не должен появиться раньше вопроса
А ещё Мониторить отставание и выводить из балансировки сильно отставшие реплики
Подробно
При асинхронной репликации лидер подтверждает запись, не дожидаясь реплик. Обычно реплики отстают на миллисекунды, но под нагрузкой, при долгих транзакциях, тяжёлых миграциях или сетевых проблемах — на секунды и минуты. Тогда возможны аномалии:
- не вижу своё изменение — сохранил профиль, а при перезагрузке страницы прочитал старую версию с отставшей реплики;
- откат во времени — первый запрос попал на свежую реплику, второй — на отставшую: комментарий появился и исчез;
- нарушение причинности — вижу ответ на вопрос, которого ещё нет (они на разных репликах или шардах).
Решения для «вижу своё» (read-your-writes):
- читать с лидера данные, которые пользователь мог менять (свой профиль, свои заказы), а чужие — с реплик;
- читать с лидера в течение короткого времени после записи пользователя (метка «писал в последние N секунд» в сессии или cookie);
- запоминать позицию журнала (LSN в PostgreSQL, GTID в MySQL) после записи и читать только с реплики, которая её применила, — иначе с лидера. Так делают ProxySQL, драйверы с causal consistency в MongoDB;
- синхронная репликация для критичных данных — дороже по задержке записи.
Монотонное чтение — закрепить пользователя за одной репликой (хеш user_id), чтобы последовательные чтения не шли назад во времени.
Причинная согласованность — писать связанные данные в один шард или передавать «версию» прочитанного, чтобы зависимые данные читались не старше неё.
В интерфейсе иногда достаточно оптимистичного обновления: показать сохранённое сразу из ответа на запись, не перечитывая.
Эксплуатация:
- метрика отставания каждой реплики (
pg_stat_replication,replay_lag;Seconds_Behind_Master) и алерт; - исключать из балансировки реплики с отставанием выше порога;
- не гонять на репликах для пользовательских запросов тяжёлую аналитику — она тормозит применение журнала (или конфликтует с ним).
Пример
def get_profile(user_id, session):
# недавно писал — читаем с лидера, иначе с реплики
if session.get("wrote_at", 0) > time.time() - 5:
return primary.fetch_profile(user_id)
return replica_for(user_id).fetch_profile(user_id) # одна реплика на пользователя — монотонноЧто хотят услышать
- Причина: асинхронная реплика отстаёт.
- Названия гарантий: read-your-writes, монотонное чтение, причинность.
- Конкретные приёмы: чтение с лидера после записи, позиция журнала, привязка к реплике.
- Мониторинг отставания и вывод отставших реплик.
Частые ошибки
- Лечить включением синхронной репликации для всего.
- Не различать чтение своих и чужих данных.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✗Ошибка базы: реплики всегда синхронны
- ✗Нужно отключить кэш браузера
- ✓Чтение с отставшей реплики; лечится read-your-writes
- ✗Запись потерялась на лидере, нужно писать дважды
Что спросят дальше
Связанные вопросы
- Какие бывают схемы репликации и чем они отличаются? Middle
- После перехода на отдельное хранилище для чтения пользователи жалуются: сохранённое изменение не сразу видно в списке. Как правильно к этому отнестись? Middle
- Пользователь публикует комментарий и должен сразу видеть его в ленте, а остальным допустима задержка в несколько секунд. Какие гарантии согласованности вы заложите и как это реализуете? Middle
- Какие промежуточные гарантии находятся между строгой и итоговой согласованностью? Middle
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.