Вы настроили retention.ms = 86400000 (24 часа) и отправили тестовое сообщение. Через сколько времени реально удалится сообщение?

a) Ровно через 24 часа
b) Через 24-25 часов
c) Через 30+ часов
d) Никогда не удалится

Подсказка: Через 24 часа Вы пытаетесь его прочитать... и оно всё ещё там!
Почему? Давайте разберёмся на примере реального сценария и в конце узнаем, сколько же реально хранится сообщение.

В Kafka нет моментального удаления сообщений по истечении срока жизни (retention time). Управляет этим процессом логическая сегментация и конфигурация топиков.

Хранение сообщений

Из чего состоит топик с сообщениями
Из чего состоит топик с сообщениями

Что такое сегмент и почему он так важен?

Брокеры разбивают файлы с сообщениями на отдельные части, называемые сегментами. Сегментирование упрощает применение настроек хранения данных и извлечение записей по смещению.
При отправке сообщения в топик брокер добавляет запись в конец активного сегмента. Когда файл журнала достигает определенного размера (по умолчанию 1 ГБ), брокер создает новый сегмент, но продолжает использовать ранее созданные сегменты для обслуживания запросов потребителей.

Представьте лог топика не как один огромный файл, а как последовательность сегментов (файлов). Например:
00000000000000000000.log00000000000000005368.log00000000000000010678.log

Kafka удаляет данные целыми сегментами, а не отдельными сообщениями.

Ниже проиллюстрирован каталог топика events.topic:

../log_dir/
├── events-topic-0/                      # Партиция 0
│   ├── 00000000000000000000.log         # Сегмент 1: данные сообщений
│   ├── 00000000000000000000.index       # Индекс offset → позиция в .log
│   ├── 00000000000000000000.timeindex   # Индекс timestamp → offset
│   ├── 00000000000000000000.snapshot    # Снапшот для transactional данных
│   ├── 00000000000000005368.log         # Сегмент 2
│   ├── 00000000000000005368.index
│   ├── 00000000000000005368.timeindex
│   ├── leader-epoch-checkpoint          # Информация о лидерах для EOS
│   └── partition.metadata               # Метаданные партиции
├── events-topic-1/                      # Партиция 1
│   ├── 00000000000000000000.log
│   ├── 00000000000000000000.index
│   └── ...
└── events-topic-2/                      # Партиция 2
    ├── 00000000000000000000.log
    ├── 00000000000000000000.index
    └── ...

00000000000000005368.log — сегмент данных

  • Назначение: Содержит фактические сообщения (key, value, headers, metadata)

  • Имя файла: {start_offset}.log (например, 5368 — offset первого сообщения)

  • Формат: Бинарный, структурированный

  • Размер: Контролируется log.segment.bytes (по умолчанию 1GB)

Когда сегмент "уходит на пенсию" (становится неактивным)?

Три условия закрытия сегмента:

  1. По размеру (log.segment.bytes = 1GB)

  2. По времени (log.roll.ms = 7 дней)

  3. По индексу (log.index.size.max.bytes- это не самы очевидны вариант закрытия сегмента)

Важно: Активный сегмент никогда не удаляется, даже если все его сообщения устарели!

Разрушаем популярное заблуждение - "Сообщение удаляется ровно в момент retention.ms после его записи"

На самом деле: Время удаления "плавающие". Сообщение, которому исполнилось retention.ms, будет удалено при следующей проверке, если весь его сегмент устарел. Проверки происходят с интервалом (log.retention.check.interval.ms), по умолчанию 5 минут). Значит, удаление может задержаться на этот интервал + время, пока сегмент не станет самым старым и неактивным.

Рассмотрим параметры конфигурации, которые влияют на удаление

Настройки действуют на уровне брокера (по умолчанию для всех топиков) или могут быть переопределены для конкретного топика.

1. Основные параметры Retention:

  • log.retention.hours / log.retention.minutes / log.retention.ms - Время, которое сообщение хранится в логе. Приоритет у самого детального (ms). Стандарт — retention.hours=168 (7 дней).

  • log.retention.bytes - Максимальный общий размер лога на партицию до удаления старых сегментов. По умолчанию -1 (не ограничено размером).

  • log.segment.bytes (по умолчанию = 1 ГБ) - Крайне важный параметр! Размер одного сегмента. Чем он больше, тем реже создаются новые сегменты и, соответственно, реже удаляются старые (так как сегмент должен "закрыться" и стать неактивным, чтобы его можно было удалить).

  • log.roll.ms / log.roll.hours (по умолчанию 168 часов или 7 дней) - максимальное время до перевода сегмента в неактивный даже если он не заполнен

2. Параметры, влияющие на "частоту" и "точность" удаления:

  • log.retention.check.interval.ms (по умолчанию 300000 мс = 5 мин) - Как часто фоновый поток проверяет сегменты на соответствие политикам удаления. Уменьшение этого значения сделает удаление более "точным" по времени, но увеличит нагрузку на брокер.

  • log.segment.delete.delay.ms (по умолчанию 60000 мс = 1 мин) - Задержка между моментом, когда сегмент становится кандидатом на удаление, и физическим удалением файла с диска.

Попробуем теперь посчитать реальное время жизни сообщения

Сценарий: Топик с умеренной нагрузкой

retention.ms = 86400000 (24 часа)
log.segment.bytes = 1GB
log.roll.ms = 7 дней (по умолчанию!)
Скорость записи: 100MB/час

При такой нагрузке для заполнения одного сегмента потребуется примерно:

1024 МБ / 100 МБ ~ 10.24 часа или 10 часов 14 минут.

Исходя из описания параметров конфигурации выше, теперь мы можем вывести некую формулу для приблизительного расчета времени жизни сообщения:

Общее_время = retention.ms + 
               Время_до_закрытия_сегмента + 
               log.retention.check.interval.ms + 
               log.segment.delete.delay.ms 
               
            = 24 часа + 10 час 14 минут + 5 минут + 1 минута 
            = 34 часа 20 минут

Итог: 24 часа ожидаемых → 34+ часа реальности

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

Выводы:

  1. Retention в Kafka — гарантия «не раньше чем», а не «ровно через»

  2. Сегм��нты — главные герои этой истории, они диктуют правила

  3. Правильная настройка сегментов важнее, чем просто установка retention

  4. Неправильная оценка времени жизни сообщений может привести к исчерпанию места на диске на борокере и привести к остановке его работы