Требуемые знания:
- module-2/01-logical-decoding-deep-dive
Жизненный цикл Replication Slots
В предыдущем уроке мы узнали, что replication slots — это “закладки” в WAL. Они гарантируют, что PostgreSQL не удалит WAL сегменты, пока Debezium их не прочитает. Это мощный механизм, но slots требуют внимательного управления.
Критическое предупреждение: Abandoned replication slot может заполнить весь диск WAL сегментами, что приведет к остановке базы данных. Это одна из самых частых проблем в production CDC.
Что такое Replication Slot?
Replication Slot — это объект PostgreSQL, который отслеживает позицию потребителя в WAL. PostgreSQL гарантирует, что все WAL сегменты после restart_lsn слота будут сохранены.
0/1000000
0/2000000
0/3000000
0/4000000
0/5000000
Уже прочитаны слотом
Ожидают чтения Debezium
restart_lsn: 0/3000000
Ключевые атрибуты слота
| Атрибут | Описание |
|---|---|
slot_name | Уникальное имя слота |
plugin | Output plugin (pgoutput для Debezium) |
slot_type | logical или physical |
active | Есть ли активное соединение |
restart_lsn | Позиция, с которой нужно начать при восстановлении |
confirmed_flush_lsn | Последняя подтвержденная позиция |
wal_status | reserved, extended, unreserved, lost |
Жизненный цикл слота
2. Проверить что коннектор не нужен
3. pg_drop_replication_slot()
Создание слота
Автоматически Debezium (рекомендуется):
Debezium создает слот автоматически при первом запуске коннектора:
{
"name": "inventory-connector",
"config": {
"connector.class": "io.debezium.connector.postgresql.PostgresConnector",
"slot.name": "debezium_inventory",
"database.hostname": "postgres",
"database.dbname": "inventory"
}
}
Вручную (для тестирования):
SELECT pg_create_logical_replication_slot(
'debezium_inventory', -- имя слота
'pgoutput' -- output plugin
);
Состояния слота
Active (active = true): Debezium подключен и читает изменения. Нормальное рабочее состояние.
Inactive (active = false): Нет активного соединения. Это может быть:
- Коннектор временно остановлен (rebalance, restart)
- Коннектор перманентно удален (опасно!)
Abandoned: Inactive слот, чей коннектор больше не существует. WAL будет накапливаться бесконечно.
Мониторинг: pg_replication_slots
Системное представление pg_replication_slots — ваш главный инструмент мониторинга.
Полный мониторинговый запрос
-- Комплексный мониторинг всех logical replication slots
SELECT
slot_name,
plugin,
active,
active_pid,
-- WAL retention metrics
pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn) AS lag_bytes,
pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS lag_pretty,
-- Status
wal_status,
safe_wal_size,
-- LSN positions
restart_lsn,
confirmed_flush_lsn,
-- Additional info
temporary,
catalog_xmin
FROM pg_replication_slots
WHERE slot_type = 'logical'
ORDER BY lag_bytes DESC NULLS LAST;
Интерпретация результатов
slot_name | plugin | active | lag_bytes | lag_pretty | wal_status
--------------------+----------+--------+-----------+------------+------------
debezium_inventory | pgoutput | t | 16384 | 16 kB | reserved
old_abandoned_slot | pgoutput | f | 5368709120| 5120 MB | unreserved
Здоровый слот:
active = truelag_bytes< 100MB (зависит от нагрузки)wal_status = 'reserved'
Проблемный слот:
active = false+ высокийlag_byteswal_status = 'unreserved'или'lost'
wal_status: что означает?
| Значение | Описание | Действие |
|---|---|---|
reserved | WAL зарезервирован, всё в порядке | Норма |
extended | WAL превысил max_wal_size, но слот его держит | Следить |
unreserved | WAL может быть удален в любой момент | Опасно |
lost | WAL уже удален, слот невосстановим | Пересоздать коннектор |
wal_status = 'lost'означает, что коннектор отстал слишком сильно. После удаления слота потребуется полный resnapshot базы данных.
Проверка знанийСлот показывает wal_status='extended'. Это нормально или повод для беспокойства?
Критическая опасность: Abandoned Slots
Как slot заполняет диск
День 1: Коннектор остановлен, slot inactive
WAL retention: 100 MB
День 2: База продолжает работать
WAL retention: 500 MB
День 3: Slot забыли
WAL retention: 2 GB
День 7: Диск на 80%
WAL retention: 10 GB
День 10: ДИСК ПОЛНЫЙ
PostgreSQL: read-only mode / crash
PostgreSQL не удаляет WAL сегменты, пока slot их не прочитал. Если slot inactive и забыт — WAL растет бесконечно.
Как обнаружить abandoned slots
-- Находим inactive slots с большим lag (потенциально abandoned)
SELECT
slot_name,
active,
pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) AS retained_wal,
wal_status
FROM pg_replication_slots
WHERE slot_type = 'logical'
AND active = false
AND pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn) > 1073741824; -- > 1 GB
Безопасное удаление slots
ВНИМАНИЕ:
active = falseНЕ означает “безопасно удалить”! Коннектор может быть временно остановлен (rebalance, обновление).
Чеклист перед удалением
-
Проверить Kafka Connect: Существует ли коннектор с этим slot_name?
curl http://localhost:8083/connectors | jq -
Проверить статус коннектора:
curl http://localhost:8083/connectors/[name]/status | jq -
Связаться с командой: Убедиться, что коннектор действительно не нужен.
-
Документировать: Записать причину удаления в runbook.
Удаление слота
-- Только после подтверждения, что коннектор удален!
SELECT pg_drop_replication_slot('old_abandoned_slot');
Если slot active, сначала остановите коннектор:
# Удалить коннектор в Kafka Connect
curl -X DELETE http://localhost:8083/connectors/inventory-connector
# Затем удалить slot в PostgreSQL
psql -c "SELECT pg_drop_replication_slot('debezium_inventory');"
max_slot_wal_keep_size: Страховка от disk exhaustion
PostgreSQL 13+ добавил параметр max_slot_wal_keep_size — лимит WAL на каждый slot.
-- postgresql.conf или ALTER SYSTEM
max_slot_wal_keep_size = '10GB'
Как это работает
| WAL retention | wal_status | Поведение |
|---|---|---|
| < max_slot_wal_keep_size | reserved | WAL сохраняется |
| > max_slot_wal_keep_size | unreserved | WAL может быть удален |
| WAL удален | lost | Slot невосстановим |
Рекомендация: Всегда устанавливайте max_slot_wal_keep_size в production:
-- Рекомендуемые значения
max_slot_wal_keep_size = '10GB' -- Небольшие БД (< 100GB)
max_slot_wal_keep_size = '50GB' -- Средние БД
max_slot_wal_keep_size = '100GB' -- Большие БД с высокой нагрузкой
Компромисс: Слишком маленький лимит — connector может потерять WAL при кратковременных проблемах. Слишком большой — не защитит от disk exhaustion. Выбирайте исходя из свободного места на диске.
Проверка знанийЧто происходит, когда WAL retention слота превышает max_slot_wal_keep_size?
Alerting: Prometheus + Grafana
Метрики для мониторинга
-- Метрика: replication_slot_lag_bytes
-- Использовать с pg_exporter или custom exporter
SELECT
slot_name,
pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn) AS lag_bytes
FROM pg_replication_slots
WHERE slot_type = 'logical';
Примеры алертов
# Prometheus alerting rules
groups:
- name: replication_slots
rules:
# Alert: Inactive slot with growing lag
- alert: ReplicationSlotInactiveLagHigh
expr: |
pg_replication_slot_lag_bytes{active="false"} > 1073741824
for: 30m
labels:
severity: warning
annotations:
summary: "Inactive replication slot {{ $labels.slot_name }} has >1GB lag"
description: "Slot may be abandoned. Check if connector exists."
# Alert: WAL status is 'lost'
- alert: ReplicationSlotWalLost
expr: |
pg_replication_slot_wal_status{wal_status="lost"} == 1
for: 5m
labels:
severity: critical
annotations:
summary: "Replication slot {{ $labels.slot_name }} WAL is lost"
description: "Connector needs full resnapshot. WAL was deleted."
# Alert: High lag on active slot
- alert: ReplicationSlotLagHigh
expr: |
pg_replication_slot_lag_bytes{active="true"} > 5368709120
for: 15m
labels:
severity: warning
annotations:
summary: "Replication slot {{ $labels.slot_name }} lag >5GB"
description: "Connector may be slow or stuck."
Документирование slots
Ведите документацию о том, какой коннектор владеет каким слотом:
| Slot Name | Connector | Owner Team | Created | Notes |
|----------------------|-------------------|------------|------------|--------------|
| debezium_inventory | inventory-connector| Platform | 2026-01-15 | Main CDC |
| debezium_orders | orders-connector | Orders | 2026-01-20 | Order events |
| debezium_analytics | (DELETED) | Analytics | 2026-01-10 | To cleanup |
Это спасет от случайного удаления активных слотов и поможет найти abandoned.
Операционный runbook
При обнаружении inactive slot с высоким lag
-
Проверить Kafka Connect:
curl http://localhost:8083/connectors/[connector-name]/status -
Если коннектор существует и FAILED:
- Проверить логи:
docker logs connect 2>&1 | grep -i error - Перезапустить task:
curl -X POST .../tasks/0/restart
- Проверить логи:
-
Если коннектор не существует:
- Проверить с командой-владельцем
- Если подтверждено удаление — drop slot
-
Если неясно:
- НЕ удалять slot
- Эскалировать до владельца
- Следить за ростом lag
При wal_status = ‘lost’
- Slot невосстановим — WAL уже удален
- Удалить slot:
SELECT pg_drop_replication_slot('...'); - Удалить и пересоздать коннектор
- Коннектор выполнит полный snapshot
- Провести post-mortem: почему slot остался без присмотра?
Что дальше?
Мы изучили, как управлять replication slots. Следующий вопрос: как настроить PostgreSQL для оптимальной производительности CDC?
В следующем уроке мы рассмотрим конфигурацию WAL: wal_level, max_wal_senders, влияние на производительность и метрики для мониторинга.
Ключевые выводы
- Replication Slots — закладки в WAL, гарантирующие, что Debezium не пропустит изменения
- active = false НЕ означает “безопасно удалить” — коннектор может быть временно остановлен
- Abandoned slots накапливают WAL бесконечно, заполняя диск
- max_slot_wal_keep_size — критически важный параметр для production
- Мониторинг pg_replication_slots — обязательная практика
- wal_status = ‘lost’ — slot невосстановим, требуется полный resnapshot
- Документируйте ownership — какой коннектор владеет каким слотом
Проверьте понимание
Закончили урок?
Отметьте его как пройденный, чтобы отслеживать свой прогресс