1. Основы топиков: партиции, сегменты и структура логов
Основы топиков: партиции, сегменты и структура логов
Добро пожаловать в курс «Архитектура и управление топиками в Apache Kafka». Это первая статья, и мы начнем с фундамента, на котором держится вся экосистема Kafka. Многие воспринимают Kafka просто как «очередь сообщений», но технически это распределенный журнал фиксации изменений (distributed commit log). Чтобы понять, как управлять данными, масштабировать систему и обеспечивать надежность, необходимо разобраться в анатомии топика.
В этой статье мы спустимся с логического уровня (топик) на физический уровень (сегменты на диске) и разберем, как именно Kafka хранит ваши данные.
Что такое Топик?
На самом высоком уровне абстракции находится Топик (Topic). Топик — это именованный поток записей (сообщений). Если проводить аналогию с базами данных, топик похож на таблицу в реляционной базе данных или на папку в файловой системе.
Топики в Kafka являются логическими сущностями. Вы отправляете сообщения в топик «orders» (заказы) или «logs» (логи), и потребители (consumers) подписываются на эти топики, чтобы читать данные. Однако сам по себе топик не является единым монолитным файлом.
Ключевые характеристики топика:
Партиции: Единица масштабирования
Если бы топик хранился на одном сервере в виде одного файла, мы бы быстро столкнулись с ограничениями по скорости записи и объему диска. Чтобы решить эту проблему, Kafka разбивает топик на Партиции (Partitions).
Партиция — это упорядоченная, неизменяемая последовательность записей, к которой постоянно добавляются новые данные. Это и есть тот самый «журнал» (log).
!Топик, разделенный на три партиции, обеспечивающий параллельную обработку данных.
Зачем нужны партиции?
Гарантия порядка (Ordering Guarantee)
Это один из самых важных концептов в Kafka, который часто вызывает недопонимание.
> Kafka гарантирует порядок сообщений ТОЛЬКО в пределах одной партиции.
Если вы отправили сообщение А, а затем сообщение Б в одну и ту же партицию, то потребитель гарантированно прочитает сначала А, потом Б. Однако, если сообщения попали в разные партиции, глобальный порядок между ними не гарантируется.
Структура лога и Оффсеты
Каждая запись в партиции получает последовательный порядковый номер, который называется смещением или оффсетом (offset).
Оффсет (Offset)
Оффсет — это просто целое число (64-битный integer), которое монотонно возрастает. Первое сообщение в партиции имеет оффсет 0, следующее — 1, и так далее.
Важные свойства оффсета: * Уникальность: Оффсет уникален только в рамках своей партиции. Сообщение с оффсетом 5 в Партиции 0 и сообщение с оффсетом 5 в Партиции 1 — это совершенно разные данные. * Идентификация: Оффсет служит единственным идентификатором сообщения внутри партиции. Потребители используют оффсеты, чтобы «запомнить», где они остановились при чтении.
Неизменяемость (Immutability)
Лог в Kafka является append-only (только для добавления). Как только запись записана в партицию и получила оффсет, она становится неизменяемой. Вы не можете отредактировать сообщение или удалить его из середины очереди, как это можно сделать в базе данных SQL.
Это ограничение дает колоссальное преимущество в производительности. Запись в конец файла — это последовательная операция ввода-вывода (Sequential I/O), которая на магнитных жестких дисках (HDD) работает в разы быстрее, чем случайный доступ (Random Access).
Сегменты: Физическое хранение
Мы выяснили, что топик делится на партиции. Но как партиция выглядит на жестком диске сервера? Если партиция будет жить вечно, она превратится в один гигантский файл, который неудобно хранить и очищать.
Поэтому каждая партиция физически разбивается на Сегменты (Segments).
Файловая структура
На диске брокера каждая партиция представлена директорией. Имя директории обычно имеет формат <topic_name>-<partition_id>. Например, orders-0.
Внутри этой директории находятся файлы сегментов. Сегмент состоит из двух основных файлов:
.log файл: Содержит сами данные (сообщения)..index файл: Содержит индекс, который сопоставляет логические оффсеты с физической позицией байтов в файле .log.!Физическая структура сегментов партиции на диске.
Активный сегмент (Active Segment)
В любой момент времени для записи доступен только один сегмент — активный сегмент. Все новые сообщения пишутся в него. Остальные (старые) сегменты закрыты для записи и используются только для чтения.
Когда активный сегмент достигает определенного предела (по размеру или по времени), он «закрывается» (rolled), и создается новый активный сегмент.
Имя файла сегмента — это оффсет первого сообщения в этом сегменте. Например:
* 00000000000000000000.log (содержит сообщения с оффсетами 0...1023)
* 00000000000000001024.log (содержит сообщения с оффсетами 1024...)
Индексы
Зачем нужен файл .index? Представьте, что потребитель хочет прочитать сообщение с оффсетом 5000. Без индекса Kafka пришлось бы сканировать .log файл с самого начала, чтобы найти нужное сообщение. Это медленно.
Индекс использует разреженную индексацию (sparse indexing). Он хранит указатели не на каждое сообщение, а, например, на каждые 4 КБ данных. Kafka находит в индексе ближайшую позицию, а затем сканирует небольшой участок лога до нужного сообщения.
Жизненный цикл данных
Понимание сегментов важно для понимания того, как Kafka удаляет старые данные. Kafka не удаляет сообщения по одному. Удаление происходит целыми сегментами.
Существует две основные стратегии очистки (Retention):
Важно помнить: активный сегмент никогда не удаляется, даже если срок хранения данных истек.
Резюме
Подведем итоги иерархии хранения данных в Kafka:
В следующей статье мы подробно разберем, как производители (Producers) выбирают, в какую именно партицию отправить сообщение, и как работает балансировка нагрузки.