Схема по материалу: Как я мониторю репликацию PostgreSQL и не путаю лаг в байтах с задержкой сервиса
Схема основана на материале «Как я мониторю репликацию PostgreSQL и не путаю лаг в байтах с задержкой сервиса» и его сигналах. Первичный сервер, WAL sender, канал TLS, WAL receiver и replay на реплике показаны как разные этапы с отдельными признаками состояния, объёма и времени.

Контекст внедрения

В одном из внедрений IT Fresh я получил задачу не просто показать зелёную реплику PostgreSQL, а дать дежурному объяснимый ответ: соединена ли она с ожидаемым источником, получает ли WAL, успевает ли записывать и применять изменения, и какой риск это создаёт для сервиса. Название организации, адреса узлов и состав баз здесь намеренно не раскрываю. Исходная панель содержала один вычисленный lag и состояние процесса, поэтому при инциденте команда видела число, но не понимала, относится оно к передаче, записи или replay. Я сначала зафиксировал топологию: какая primary ожидается, какие физические standby существуют, где разрешено promotion, используется ли синхронное подтверждение и какие replication slots закреплены за репликами. Затем разделил наблюдение с обеих сторон. На primary источник фактов — pg_stat_replication по каждой сессии WAL sender; на standby — pg_stat_wal_receiver и функции состояния recovery. Я решил не собирать тексты запросов и прикладные таблицы: для этой задачи они не нужны. Отдельными объектами стали сессия, канал, позиции LSN, применение WAL, слот, архив и роль узла. Такое разбиение сразу определило будущие items, причины событий и порядок проверки.

Что показал первый разбор

Первый совместный разбор исторических значений показал, почему прежний индикатор вводил в заблуждение. В pg_stat_replication строка могла оставаться со state равным streaming, но sent_lsn, write_lsn, flush_lsn и replay_lsn расходились по-разному. Это означало, что сетевой сеанс жив, однако один из следующих этапов не поспевает. Я также вынес sync_state отдельно: async сообщает об асинхронной реплике, sync или quorum связывает её с выбранным режимом синхронного подтверждения, а potential не делает реплику фактически синхронной. Значение нужно сопоставлять с synchronous_standby_names и договорённостью об архитектуре, а не превращать само слово sync в гарантию доступности. На standby строка pg_stat_wal_receiver дала status, адрес отправителя, received timeline, written_lsn, flushed_lsn и признаки последнего сообщения. Если ожидаемой сессии нет, я проверяю не только сеть и pg_hba.conf. Promotion мог законно изменить роль узла; после переключения появляется другая timeline, и старая пара primary—standby перестаёт быть правильной. Поэтому apparent break может оказаться следствием успешного переключения, а не поломкой репликации. Без инвентаря ролей такой случай рождает шум и опасное желание вернуть уже неактуальное соединение.

Почему два лага нельзя склеивать

Для объёмного отставания я вычисляю разности между текущей WAL-позицией primary и позициями sent, write, flush, replay с помощью штатного сравнения LSN. Результат в байтах отвечает на вопрос, сколько WAL отделяет этапы. Он не равен секундам простоя сервиса: при интенсивной записи небольшой временной промежуток создаёт большой объём, а при почти неподвижной базе давно применённая транзакция может оставлять близкие LSN. Временной сигнал я строю отдельно по replay timestamp на standby и наблюдаемому времени сбора. Он показывает, когда была воспроизведена последняя транзакция, но при отсутствии новых транзакций возраст отметки растёт, хотя реплика уже догнала primary. Поэтому рядом обязательно проверяю байтовую дистанцию и активность генерации WAL. Есть ещё принципиальная оговорка: разность локального now и отметки с другого узла недостоверна при clock skew. До вывода о задержке сервиса я проверяю синхронизацию часов и источник времени на primary, standby и Zabbix. Даже при исправных часах replay delay остаётся техническим свидетельством, а не прямым измерением пользовательской недоступности. Я отказался от универсальной фиксированной границы: профиль записи, канал, назначение реплики и допустимая потеря данных различаются, поэтому условия задаются для конкретной роли и согласованного риска.

Коллектор с минимальными правами

Для сбора я создал отдельную login role мониторинга без SUPERUSER, создания баз, ролей, репликации и записи в прикладные схемы. Ей разрешено подключение к выделенной служебной базе и выполнение только согласованных read-only запросов к доступным статистическим представлениям; если конкретной версии нужны дополнительные видимые поля, право добавляется точечно и документируется, а не заменяется широким доступом. В pg_hba.conf я ограничил источник адресом коллектора, базой, ролью и методом аутентификации. Соединение потребовал через TLS с проверкой сертификата и имени сервера; пароль или сертификат клиента хранится как защищённый секрет Zabbix и не попадает в key, журнал или текст события. На primary запрос читает pg_stat_replication, состояние slots и pg_stat_archiver. На standby отдельный запрос читает pg_stat_wal_receiver, recovery state, received и replay positions, timestamp и timeline. Коллектор возвращает также свой код результата и время успешного чтения: пустая выборка не подменяет ошибку соединения нулём. Я проверил поведение в короткой транзакции, чтобы снимок не оставался закэшированным между циклами. Запросы не вызывают promotion, checkpoint, switch WAL или изменение слота. Так дежурный получает диагностические факты, но мониторинговая учётная запись не способна менять данные или конфигурацию кластера.

Как я разложил данные в Zabbix

В Zabbix я оформил отдельный template PostgreSQL replication и связал его с узлами базы, не смешивая метрики с общей проверкой TCP. Мастер-элементы получают компактные структурированные ответы для primary и standby, а dependent items извлекают состояние сессии, sync_state, четыре позиции LSN, байтовые разности, receiver status, replay timestamp, timeline, archive counters и свежесть коллектора. Low-level discovery создаёт сущности по ожидаемым standby и физическим replication slots. В макросы LLD передаются устойчивые технические идентификаторы и обезличенные подписи; hostname клиента не используется как единственный ключ, потому что он может измениться или повториться. Для каждого слота я показываю active, restart_lsn и удерживаемый объём WAL. Неактивный слот важен не только как пропавшая реплика: он способен удерживать старые сегменты и постепенно занять файловую систему, поэтому событие связывает состояние слота, рост retained WAL и назначение. Отдельно наблюдаю failed_count и last_failed_wal из pg_stat_archiver: исправный streaming не отменяет сбой WAL archive, который влияет на другую линию восстановления. Триггеры зависят от свежести мастер-элемента, чтобы старая метрика не выглядела текущей. Dashboard оставляет байты, время, сессию, режим, архив и роль разными рядами, а корреляция выполняется только в событии и регламенте.

Проверка без риска для данных

Перед вводом я сверил значения Zabbix с read-only SQL на обоих узлах и записал исходные позиции, роль, timeline, состояние слота и нормальный поток WAL. Для управляемой проверки выбрал реплику, которую владелец заранее разрешил кратковременно задержать, и согласованное окно. Я приостановил replay штатным обратимым действием только на этой standby; primary продолжала работу, прикладных записей и переключения ролей тест не выполнял. Ожидаемое свидетельство было определено заранее: receiver остаётся подключённым, received или flushed position движется, replay_lsn останавливается, байтовый разрыв применения растёт, а соответствующее событие Zabbix открывается без ложного сообщения о сетевом разрыве. Стоп-условиями стали неожиданный рост диска, влияние на production workload, потеря сессии или выход за согласованное время. Rollback состоял в немедленном возобновлении replay той же штатной командой. После этого я наблюдал сокращение очереди до обычного диапазона и закрытие события по актуальному опросу. Если безопасная пауза не разрешена, проверку провожу на выделенной реплике или ограничиваюсь сопоставлением штатных событий; намеренно рвать рабочую сеть, удалять слот, ломать архив либо инициировать promotion ради проверки нельзя. Результат подтверждает конкретный путь сигналов, но не обещает скорость восстановления при любом будущем объёме WAL.

Что делать дежурному

В регламенте я начинаю с проверки свежести данных Zabbix и ошибки коллектора. Затем дежурный подтверждает текущую роль каждого узла, recovery state, системный identifier и timeline: это защищает от расследования старой топологии после promotion. На primary он ищет ожидаемую строку pg_stat_replication, читает state и sync_state, сопоставляет sent, write, flush и replay. На standby проверяет pg_stat_wal_receiver, адрес источника, status и момент последнего сообщения. Если сессии нет, ветка включает DNS, маршрут, порт, TLS, сертификат, pg_hba.conf, пароль, права и журналы PostgreSQL, но не ограничивается ими. При живой сессии сравниваются LSN-этапы: рост sent—write указывает на путь доставки, write—flush требует внимания к записи, flush—replay — к применению и ресурсам standby. Временную задержку дежурный трактует только после проверки часов и наличия новых WAL. Параллельно он смотрит slots и удержание WAL, свободное место, ошибки WAL archive, restart или обслуживание. Последний шаг — сверить, не было ли согласованного переключения. Никаких команд изменения из мониторинговой сессии регламент не содержит. Эскалация передаёт владельцам базы и сервиса факты: роль, timeline, позиции, временные отметки, состояние архива, длительность и затронутую реплику, без клиентских имён и содержимого данных.

Граница ответственности RPO и RTO

Я отдельно закрепил, что мониторинг предоставляет наблюдения, но не назначает бизнес-требования. RPO отвечает за допустимую потерю данных и влияет на то, какой объём или возраст неприменённых изменений требует реакции. RTO определяет допустимое время восстановления сервиса и включает больше, чем догон реплики: решение о переключении, запуск зависимостей, проверку приложения, маршрутизацию трафика и работу людей. Владельцы бизнес-сервиса утверждают RPO и RTO; владельцы PostgreSQL и платформы подтверждают достижимую архитектуру, режим synchronous или asynchronous, ёмкость WAL, slots, архив и порядок promotion; команда мониторинга реализует проверяемые сигналы и доставку события. Дежурный не меняет sync_state и не выполняет promotion только потому, что график пересёк техническую линию. Он оценивает сочетание состояния сессии, LSN lag, replay delay, clock skew, удержания WAL, archive failures, timeline и влияния на сервис, затем эскалирует назначенному владельцу в пределах согласованного времени. Если фактический профиль WAL изменился, пороги и ёмкость пересматриваются совместно, а не скрываются подавлением события. Эта граница не ослабляет контроль: она не позволяет выдать техническую метрику за обещание непрерывности и оставляет решение о риске у тех, кто отвечает за данные и доступность.

Сигналы, которые сопоставляю

  • pg_stat_replication: state, sync_state, sent_lsn, write_lsn, flush_lsn, replay_lsn и reply_time по каждому WAL sender.
  • pg_stat_wal_receiver: status, sender_host, sender_port, written_lsn, flushed_lsn, latest_end_lsn и latest_end_time на реплике.
  • Разности LSN в байтах отдельно для отправки, записи, flush и replay; replay timestamp и вычисленная сервисная задержка отдельно.
  • Состояние физических replication slots, restart_lsn, retained WAL и риск заполнения файловой системы.
  • pg_stat_archiver: failed_count, last_failed_wal, last_failed_time, archived_count и last_archived_time.
  • Роль узла, recovery state, системный identifier и timeline как контекст для обнаружения promotion или переподключения.
  • Свежесть опроса, ошибка SQL-коллектора, состояние TLS и наличие ожидаемой репликационной сессии как самостоятельные признаки.

Отвергнутые альтернативы

  • Свести все отклонения к одному числу lagБайтовая дистанция между LSN описывает объём WAL, а время последнего replay — временной контекст; одинаковое число байт при разной скорости записи означает разный риск.
  • Считать отсутствие sender только сетевым обрывомПричиной могут быть promotion, смена timeline, новая primary, удалённый или переименованный standby, ошибка прав либо устаревшая ожидаемая топология.
  • Назначить один постоянный порог всем репликамДопуск зависит от профиля WAL, назначения реплики, согласованных RPO и RTO, окна обслуживания и способности площадки наверстать очередь.
  • Проверять только streaming и sync_stateСессия может существовать при отставании replay, накоплении WAL слотом, проблеме архива или неверной интерпретации режима подтверждения транзакций.

Конфигурация и сбор

Отдельная read-only login role PostgreSQL, подключение только от Zabbix collector по точному правилу pg_hba.conf через TLS с проверкой сервера; без прав записи, REPLICATION, SUPERUSER и доступа к прикладным данным.

  • На primary прочитать pg_stat_replication, физические replication slots и pg_stat_archiver, сохраняя ошибку отдельно от пустого результата.
  • На standby прочитать pg_stat_wal_receiver, recovery state, LSN, replay timestamp и timeline.
  • Передать структурированный результат в master items, создать dependent items и LLD для ожидаемых standby и slots.
  • Проверить свежесть, TLS, отсутствие секретов и корректность раздельных единиц: bytes для LSN и seconds только для временного наблюдения.

Контролируемая проверка и свидетельство

В согласованное окно на заранее выбранной реплике кратко приостанавливается только replay. Ожидаются продолжающийся приём WAL, остановка replay_lsn, рост соответствующей байтовой дистанции и адресное событие Zabbix. Откат — немедленно возобновить replay, подтвердить сокращение очереди и закрытие события; при влиянии на сервис или диск тест прекращается.

Фрагмент рабочего регламента

  • Проверить свежесть items и ошибку коллектора, затем подтвердить роли узлов и timeline.
  • Сопоставить pg_stat_replication на primary с pg_stat_wal_receiver на standby, включая state и sync_state.
  • Разобрать LSN-разности по этапам, отдельно проверить replay timestamp и синхронизацию часов.
  • Проверить slots, удержание WAL, свободное место и WAL archive failures; передать факты владельцам PostgreSQL и сервиса.

Откат

Откат теста возобновляет replay на выбранной standby и подтверждает возврат к обычному потоку. Откат внедрения отключает только новые template links, items, triggers и LLD, восстанавливает прежнее правило pg_hba.conf и отзывает выделенную роль; replication slots, архив, режим синхронизации и топология не изменяются.

Ограничения вывода

Статистические представления дают состояние в момент опроса и не доказывают готовность приложения после failover. Байты LSN нельзя переводить в секунды без контекста скорости WAL; replay timestamp и межузловые расчёты зависят от часов. Допуски задаются по роли реплики, профилю нагрузки и утверждённым RPO/RTO, а не единым числом.

Источники

  1. 27.2. The Cumulative Statistics System
  2. 26.2. Log-Shipping Standby Servers
  3. 19.6. Replication
  4. 3 Low-level discovery