Safekeeper

Stable

Как Safekeeper держит WAL quorum и почему durability в SPG99 не зависит от жизни одного compute.

Обновлено: 5 марта 2026 г.

Safekeeper — это внутренний WAL‑сервис SPG99, который отвечает за durability записей. Если говорить совсем просто, Safekeeper — это место, куда платформа сначала надёжно складывает историю изменений PostgreSQL, прежде чем считать её безопасной.

Safekeeper не исполняет SQL, не принимает пользовательские DSN‑подключения и не заменяет PostgreSQL. Его задача другая:

  • принять WAL от Compute;
  • удержать её на нескольких узлах;
  • подтвердить durable‑границу;
  • отдать эту историю дальше Pageserver и следующему поколению Compute.

Для пользователя это означает очень важную вещь: данные в SPG99 защищаются не за счёт «вечного» локального диска конкретного Compute‑узла, а за счёт WAL quorum в Safekeeper.

Именно поэтому база в SPG99 может:

  • быстро запускаться по требованию;
  • работать на ephemeral Compute;
  • безопасно останавливаться при простое;
  • переживать потерю конкретного worker или переезд на другой Compute;
  • не терять уже подтверждённые изменения только потому, что старый worker исчез.

Какое место Safekeeper занимает в цепочке

Типовая цепочка SPG99 выглядит так:

пользователь / Console / API
    -> Control Plane
    -> Gateway
    -> Compute
    -> Safekeeper + Pageserver + Object Storage

Если расписать жизненный цикл записи по шагам:

  1. Пользователь подключается к базе через Gateway.
  2. Gateway приводит клиента к живому Compute.
  3. Compute исполняет SQL внутри PostgreSQL.
  4. Когда PostgreSQL генерирует WAL, Compute отправляет WAL сразу в несколько Safekeeper.
  5. Safekeeper принимает WAL, пишет её в локальный журнал и подтверждает границу записи.
  6. После quorum flush эта WAL‑граница считается durable.
  7. Pageserver подписывается на WAL из Safekeeper и материализует историю в storage‑состояние базы.
  8. При следующем cold start новый Compute берёт basebackup из Pageserver и продолжает работу с WAL‑истории, сохранённой в Safekeeper.

Из этого следует главный архитектурный смысл Safekeeper: это не «архив сбоку», а центральный слой надёжности записи в SPG99.

Чем Safekeeper отличается от других сервисов

Чтобы не путаться:

  • Control Plane создаёт tenants и базы, хранит каталог и повышает writer term.
  • Gateway принимает пользовательские подключения и маршрутизирует их к Compute.
  • Compute исполняет запросы и генерирует WAL.
  • Pageserver превращает историю WAL в storage‑состояние и отдаёт basebackup.
  • Safekeeper держит WAL quorum и durable‑границу записи.

Если сформулировать очень коротко:

  • Compute создаёт WAL;
  • Safekeeper делает WAL надёжным;
  • Pageserver делает из этой истории стартуемое storage‑состояние;
  • Control Plane и Gateway связывают всё это в единый продукт.

Главная роль Safekeeper для пользователя

Safekeeper решает четыре прикладные задачи:

1. Делает коммиты надёжными в serverless‑модели

Уже подтверждённая WAL‑история сохраняется в quorum, даже если Compute можно остановить или заменить.

2. Отделяет durability от lifecycle Compute

Данные не привязаны к одному контейнеру, VM или локальному PGDATA.

3. Даёт Pageserver источник истины по WAL

Pageserver не угадывает историю, а получает её из Safekeeper.

4. Позволяет поднимать новый Compute без ручного восстановления

Новый writer опирается на тот WAL, который уже удержан Safekeeper quorum.

Основные сущности Safekeeper

Tenant, database, timeline

Для Safekeeper WAL‑история адресуется не по пользователю и не по DSN, а по тройке:

tenant + db + timeline

Именно по этой тройке сервис понимает, к какой базе относится WAL‑поток.

WAL и LSN

Safekeeper хранит не «таблицы», а последовательность WAL‑изменений. Для пользователя ключевая идея такая: если SQL‑операция изменила данные, её след сначала попадает в WAL, и именно этот WAL Safekeeper делает надёжным.

Важные LSN‑границы:

  • next_lsn — до какой позиции WAL уже локально дописан;
  • durable_lsn — до какой позиции WAL уже считается durable;
  • flush_lsn / commit_lsn — практическое отражение той же безопасной границы.

WAL segments

WAL режется на сегменты. В текущей схеме по умолчанию это 16 MiB. На локальном диске используется два основных состояния:

  • .partial — сегмент, в который WAL ещё дописывается;
  • .ready — завершённый сегмент, который можно выгружать в object storage и использовать для backfill.

Writer term

Writer term — это номер поколения активного writer. Control Plane повышает его при запуске нового поколения Compute, а Safekeeper принимает WAL только от актуального term. Это один из ключевых механизмов защиты от split‑brain.

Как выглядит путь записи и почему он надёжен

Quorum 2 из 3

В текущем контракте SPG99 Safekeeper используется как набор из трёх адресов, а WAL quorum равен 2/3. Это означает:

  • Compute отправляет append сразу на три узла;
  • как только два узла успешно подтвердили append, write path может двигаться дальше;
  • как только два узла успешно подтвердили flush, соответствующая WAL‑граница считается quorum‑durable;
  • третий узел может догонять чуть позже и не обязан тормозить каждую запись.

Это один из главных компромиссов между скоростью и надёжностью.

Почему это важно пользователю

Если один из трёх узлов недоступен, но два остальных работают, платформа всё ещё может держать WAL quorum. Обычно это значит, что база продолжает писать и коммиты продолжают подтверждаться. Единичный сбой не обязан автоматически останавливать сервис.

Если quorum теряется и остаётся только один рабочий узел, write durability уже нельзя честно гарантировать. Нормальное поведение платформы в этом случае — не продолжать писать «втихую unsafe», а показать деградацию и не рисковать согласованностью истории.

Почему Pageserver lag не равен потере коммита

Pageserver materialize‑ит WAL асинхронно. Это нормально. Коммит уже может быть durable в Safekeeper, даже если Pageserver ещё не догнал apply до той же точки. Для пользователя важно понимать: durability и materialization — это разные стадии.

Как Safekeeper защищает от split‑brain

Writer term нужен для того, чтобы старое поколение Compute не могло продолжать писать поверх нового. Если Safekeeper видит append с term ниже текущего, такой запрос отклоняется как stale term.

Есть и более тонкий сценарий: новый term может начать писать не с самого конца локального хвоста конкретного узла, а с более ранней quorum‑durable точки. В этом случае Safekeeper обрезает лишний divergent tail и приводит журнал к согласованной safe‑границе, а не пытается склеить две конфликтующие ветки WAL.

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

Где Safekeeper хранит данные

В текущей архитектуре сервис сочетает два слоя хранения:

1. Локальный журнал на persistent storage

У каждого Safekeeper есть свой локальный WAL‑журнал на persistent volume. Это делает перезапуск Pod или процесса неравным потере всей локальной истории.

2. Object storage

Закрытые .ready‑сегменты выгружаются в S3‑совместимое объектное хранилище. Это нужно для:

  • backfill старого WAL;
  • ограничения роста локального диска;
  • более устойчивого восстановления потребителей истории.

Но принципиально важно не перепутать роли: object storage полезен и важен, но durable commit path в модели SPG99 строится на Safekeeper quorum, а не на факте окончания S3 upload.

Почему Safekeeper помогает быстрым стартам

На первый взгляд кажется, что Safekeeper нужен только для write durability. На деле его роль шире.

При cold start новый Compute опирается на безопасную quorum‑durable точку, а Pageserver строит bootstrap уже относительно неё. Это значит:

  • Compute можно запускать на новом worker;
  • Pageserver понимает, до какого LSN можно безопасно собирать стартовое состояние;
  • stop, crash или redeploy не заставляют вручную восстанавливать базу «с нуля».

То есть Safekeeper участвует не только в сохранности записи, но и в корректном и предсказуемом запуске базы после stop или crash.

Что важно помнить пользователю

  • Safekeeper — это внутренний сервис платформы. Обычно с ним не работают напрямую.
  • Надёжность данных в SPG99 не равна «данные лежат на диске Compute».
  • Basebackup и object storage не заменяют Safekeeper quorum.
  • Потеря одного Safekeeper не обязана останавливать сервис.
  • Потеря quorum — уже серьёзная деградация, и система должна это явно показывать.
  • Небольшой lag Pageserver не равен потере коммита.
  • Создание и удаление timeline лучше выполнять через Control Plane, который координирует Pageserver, Safekeeper и каталог согласованно.

Короткий итог

Safekeeper в SPG99 — это сервис, который делает serverless PostgreSQL действительно надёжным.

Для пользователя это означает:

  • durability не зависит от жизни одного Compute;
  • коммиты защищены через WAL quorum;
  • Pageserver получает корректную историю изменений;
  • новый Compute может стартовать от безопасной точки;
  • один отказ узла не обязан ломать запись;
  • платформа умеет честно останавливать unsafe‑сценарий при потере quorum, а не рисковать данными.

Подробнее о месте сервиса в общей архитектуре см. Роль сервисов в цепочке.