- PVSM.RU - https://www.pvsm.ru -
Вы настроили 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, будет удалено при следующей проверке, если весь его сегмент устарел. Проверки происходят с интервалом (log.retention.check.interval.ms), по умолчанию 5 минут). Значит, удаление может задержаться на этот интервал + время, пока сегмент не станет самым старым и неактивным.
Настройки действуют на уровне брокера (по умолчанию для всех топиков) или могут быть переопределены для конкретного топика.
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 дней) - максимальное время до перевода сегмента в неактивный даже если он не заполнен
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
Неправильная оценка времени жизни сообщений может привести к исчерпанию места на диске на борокере и привести к остановке его работы
Автор: senior__pomidor
Источник [1]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/segment/439702
Ссылки в тексте:
[1] Источник: https://habr.com/ru/articles/979026/?utm_source=habrahabr&utm_medium=rss&utm_campaign=979026
Нажмите здесь для печати.