Вы настроили retention.ms = 86400000 (24 часа) и отправили тестовое сообщение. Через сколько времени реально удалится сообщение?
a) Ровно через 24 часа
b) Через 24-25 часов
c) Через 30+ часов
d) Никогда не удалится
Подсказка: Через 24 часа Вы пытаетесь его прочитать... и оно всё ещё там!
Почему? Давайте разберёмся на примере реального сценария и в конце узнаем, сколько же реально хранится сообщение.
В Kafka нет моментального удаления сообщений по истечении срока жизни (retention time). Управляет этим процессом логическая сегментация и конфигурация топиков.
Хранение сообщений

Что такое сегмент и почему он так важен?
Брокеры разбивают файлы с сообщениями на отдельные части, называемые сегментами. Сегментирование упрощает применение настроек хранения данных и извлечение записей по смещению.
При отправке сообщения в топик брокер добавляет запись в конец активного сегмента. Когда файл журнала достигает определенного размера (по умолчанию 1 ГБ), брокер создает новый сегмент, но продолжает использовать ранее созданные сегменты для обслуживания запросов потребителей.
Представьте лог топика не как один огромный файл, а как последовательность сегментов (файлов). Например:
00000000000000000000.log, 00000000000000005368.log, 00000000000000010678.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)
Когда сегмент "уходит на пенсию" (становится неактивным)?
Три условия закрытия сегмента:
По размеру (
log.segment.bytes = 1GB)По времени (
log.roll.ms = 7 дней)По индексу (
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+ часа реальности
Конечно, Вы можете сказать, что я слукавил и оставил многие параметры по умолчанию. Но ведь именно так часто и происходит: мы меняем только те параметры, которые для нас актуальны, а про другие забываем.
Выводы:
Retention в Kafka — гарантия «не раньше чем», а не «ровно через»
Сегм��нты — главные герои этой истории, они диктуют правила
Правильная настройка сегментов важнее, чем просто установка retention
Неправильная оценка времени жизни сообщений может привести к исчерпанию места на диске на борокере и привести к остановке его работы