Программа курса

Модуль 04 / Урок 18 из 27

Репликация и Sentinel

Теория и практика

Реплики дают отказоустойчивость и разгрузку чтений, Sentinel — автоматическое переключение при падении мастера. Но фундамент всего этого — асинхронность, из которой следуют и скорость, и риски.

Асинхронная репликация

Мастер шлёт поток команд репликам, не дожидаясь подтверждения, и отвечает клиенту сразу. Отсюда:

  • Быстро: запись не платит за сеть до реплик;
  • Можно потерять хвост: запись, подтверждённая клиенту, могла не доехать до реплики. Мастер умирает → реплика становится мастером → этот хвост исчез;
  • Реплики могут отставать: чтение с реплики = чтение данных «недавнего прошлого» (stale reads). Для «записал и сразу прочитал» читайте у мастера.

Настройка реплики

# На реплике:
replicaof 10.0.0.1 6379
masterauth <пароль-мастера>        # если на мастере requirepass
replica-read-only yes               # дефолт; реплики только читают

# На мастере — минимальные гарантии записи:
min-replicas-to-write 1
min-replicas-max-lag 10
# мастер отказывается принимать записи, если нет живой реплики с лагом ≤10с

Полезное про механику:

  • Репликация инкрементальная (поток команд) + ресинхронизация через backlog (repl-backlog-size: отставание в пределах буфера — быстрое PSYNC, иначе полный RDB-трансфер);
  • Истечения TTL реплицируются явными DEL от мастера — время на реплике не искажает смерть ключей;
  • Лаг = master_repl_offset − slave_repl_offset (INFO replication); мониторьте его.

WAIT: синхронное подтверждение, когда очень надо

SET critical:payment-id 42
WAIT 1 200      # ждать подтверждения от 1 реплики, таймаут 200 мс

WAIT гарантирует, что команда достигла N реплик — reduces окно потери до нуля для конкретной записи ценой латентности. Используйте точечно для критичных операций, а не на весь трафик.

Sentinel: автоматический failover

Sentinel — отдельные процессы-наблюдатели (минимум 3, распределённые по хостам), которые:

  1. пингуют мастер и реплики; при недоступности дольше down-after-milliseconds мастера считают «объективно мёртвым» по кворуму (quorum);
  2. выбирают реплику с наименьшим лагом и повышают её в мастера;
  3. перенастраивают остальные реплики и переадресуют клиентов (клиенты, умеющие Sentinel-протокол, сами узнают новый адрес).
# sentinel.conf (на каждом из 3 хостов)
sentinel monitor mymaster 10.0.0.1 6379 2   # 2 = кворум из 3 сентинелов
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1
⚠️ Sentinel минимизирует простой, но не отменяет асинхронность: последние миллисекунды-секунды записей при падении мастера всё ещё могут потеряться. Требования «ноль потерь при failover» к обычному Redis не выполнимы без WAIT и компромиссов по латентности.

Сплит-брейн

Сетевая изоляция: старый мастер жив, но отделён от реплик и Sentinel'ов. Без защиты он продолжает принимать записи, которые потом потеряются. Защита — уже знакомая min-replicas-to-write: изолированный мастер без живых реплик перестаёт писать.

Чтение с реплик: за и против

  • За: разгрузка мастера на read-heavy трафике, геораспределённость;
  • Против: stale reads, двойная книга «кто куда ходит», при failover клиентские ошибки READONLY — нужен переподключатель;
  • Часто лучший масштабирующий ответ — не реплики на чтение, а правильный кеш (модуль 2).

Практика

  1. docker-compose: мастер + 2 реплики. Занесите данные, убедитесь, что они видны с реплик, и что запись на реплику отклоняется.
  2. Добавьте 3 Sentinel, убейте мастер — проследите выборы в логах Sentinel'ов и переподключение клиента (redis-py/lettuce умеют Sentinel нативно).
  3. Замерьте окно потери: с записью через WAIT и без — kill -9 мастера сразу после SET, что вернула новая копия данных.
  4. Оторвите мастер от реплик (iptables/docker network) с min-replicas-to-write — проверьте, что записи блокируются.
Мини-квиз

1. Почему failover может потерять подтверждённые записи? — Репликация асинхронна: хвост команд мог не доехать до новой копии.

2. Зачем min-replicas-to-write? — Чтобы изолированный/бездымный мастер не принимал записи «в пустоту» (анти-сплит-брейн).

3. Клиент читает с реплики сразу после записи. Что видит? — Возможно старые данные (stale read); для read-after-write читайте мастера.