В современных Data-driven компаниях Kafka называют «центральной нервной системой» данных. Но даже идеально настроенный кластер может стать причиной Data Loss, если конфигурация инфраструктуры не синхронизирована с реальностью бизнес-потоков. В этой статье я поделюсь кейсом из практики Platform Engineer: как неочевидный конфликт настроек приводил к потерям данных и как я решил это, внедрив метрику «Data Safety Window».

Проблема: «Дырки» в данных при плановых работах

Команда Data Engineering пришла с тревожным фидбеком: при проведении планового обслуживания DWH, когда потребители (Consumers) отключались на час-два, в финальных таблицах обнаруживались пропуски.

На первый взгляд, всё было настроено по учебнику:

  • Time-based Retention: 7 дней (данные должны лежать неделю).

  • Replication Factor: 3 (высокая отказоустойчивость).

  • Min.insync.replicas: 2 (гарантия записи).

Однако данные исчезали. Выяснилось, что при остановке консьюмеров на обслуживание, данные «вымывались» из Kafka гораздо быстрее, чем через 7 дней.

Root Cause Analysis: Когда байты сильнее времени

Как Platform Engineer, я провел аудит конфигураций. Причина оказалась классической: Byte-limit вытеснял Time-limit.

В Kafka параметры retention.ms (время) и retention.bytes (размер) работают по логике «кто первый успел». Если лимит по объему достигается раньше, чем истекают 7 дней, Kafka начинает удалять старые сегменты, чтобы освободить место.

В высоконагруженных топиках объем входящих транзакций в пиковые часы был настолько велик, что установленный лимит в байтах на партицию заполнялся всего за 20-30 минут.

Период удаления данных
Период удаления данных

Результат: Окно жизни сообщения сократилось с обещанных 7 дней до критических 25 минут. Если ETL-процесс останавливался дольше, чем на полчаса, данные «вылетали» из Kafka навсегда.

Инженерное решение: Балансировка и Capacity Planning

Проблему нельзя было решить просто «удалив лимит по байтам» — это чревато переполнением дисков и падением всего брокера. Я подошел к вопросу системно:

  1. Точный расчет Capacity: Я пересчитал максимально допустимый объем хранения для критических топиков, оставив 20% буфер для операционной системы и фоновых процессов.

  2. Тюнинг Retention: Лимиты хранения по объему были увеличены точечно там, в тех топиках в которых это было необходимо.

Главный вклад: Мониторинг «Возраста данных» (Retention Age)

Стандартные метрики (Consumer Lag или Disk Usage) полезны, но они не отвечают на главный вопрос бизнеса: «Сколько у нас есть времени на починку, если всё сломается?».

Я разработал и внедрил в Grafana панель Data Safety Window. С помощью PromQL вычислили динамическую глубину архива в реальном времени.

Формула расчета:

(Current_Offset - Oldest_Offset) / Message_Ingestion_Rate

Этот график показывает «возраст» самого старого сообщения в топике. Мы настроили алертинг по зонам:

  • Зеленая зона (> 12 часов): Спокойно чиним консьюмер, данных хватит до утра.

  • Желтая зона (< 6 часов): Нужно обратить внимание, время поджимает.

  • Красная зона (< 2 часов): Critical. Данные скоро начнут удаляться.

Запас времени до удаления данных
Запас времени до удаления данных

Не гадаем на конфигах

Чтобы не гадать, сколько данных реально лежит на диске, я реализовал расчет фактического окна хранения. Для этого используется разница между самым свежим и самым старым смещением (offset) в топике, деленная на скорость входящего потока.

Формула запроса в Grafana:

(
  sum(kafka_topic_partition_current_offset{group="$cluster", topic=~"$topic"}) 
  - 
  sum(kafka_topic_partition_oldest_offset{group="$cluster", topic=~"$topic"})
) 
/ 
sum(rate(kafka_topic_partition_current_offset{group="$cluster", topic=~"$topic"}[1h]))

Разбор формулы:

  1. Числитель: Мы берем разницу между current_offset (последнее сообщение) и oldest_offset (самое старое, еще не удаленное сообщение). Это дает нам общее количество сообщений, которое Kafka хранит в данный момент.

  2. Знаменатель: Мы считаем rate (интенсивность записи) за последний час.

  3. Результат: Получаем количество секунд, на которое нам хватает текущего объема диска при текущей нагрузке. Grafana автоматически конвертирует секунды в человекочитаемые days или hours.

Что нам говорит этот дашборд?

Посмотрите на скриншот мониторинга:

Возраст данных в топике
Возраст данных в топике

На графике четко видны «качели». В моменты пиковой нагрузки или когда Kafka начинает агрессивно чистить сегменты по лимиту retention.bytes, возраст данных резко падает (провалы почти до нуля).

  • Пики (до 6.94 days): Это когда поток данных стабилен и мы почти достигаем целевого значения retention.ms (7 дней).

  • Провалы: Это те самые «опасные моменты». На графике видно, что в определенные часы окно безопасности схлопывалось. Если бы в этот момент упал консьюмер, у инженеров не было бы и 10 минут на реакцию — данные начали бы удаляться сразу.

Теперь мы не смотрим на абстрактный «процент заполнения диска», мы смотрим на время, которое у нас есть в запасе.

Итоги: Platform Engineering как гарант надежности

Благодаря инфраструктурным изменениям и внедрению проактивного мониторинга, мы перестали терять данные. Время доступности данных в критических узлах выросло без закупки нового железа — только за счет грамотного распределения ресурсов.

Вывод:

  1. Лимиты в байтах опаснее лимитов по времени. Всегда проверяйте скорость наполнения сегментов в пиковые часы.

  2. Мониторинг должен быть человекочитаемым. Цифра «20 часов запаса» гораздо полезнее для принятия решений дежурным инженером, чем «80% занятого диска».

  3. Задача платформенного инженера — обеспечить бесшовный путь данных от источника до потребителя, понимая физику процесса на каждом этапе.