Архитектура Kafka
Kafka как распределенный журнал событий: topic, partition, offset, producer, consumer group, broker, leader, replica, ISR.
Введение: Журнал, а не почтовый ящик
Представьте банковскую выписку по счёту. В ней записаны все операции в порядке их совершения. Вы не можете изменить прошлые записи — только добавить новые. Любой может прочитать выписку с любого момента. Выписка хранится годами.
Apache Kafka устроена как такая выписка. Это не почтовый ящик (где сообщение исчезает после прочтения). Это журнал (log) — упорядоченная, неизменяемая последовательность сообщений, которая хранится определённое время.
Apache Kafka — это распределённая платформа для потоковой передачи данных. Она сочетает в себе возможности брокера сообщений, хранилища данных и движка потоковой обработки.
Для системного аналитика Kafka — это инструмент для сценариев с высокими нагрузками, где важны порядок сообщений, хранение истории и возможность повторного чтения. Kafka не заменяет очереди (RabbitMQ) — они решают разные задачи.
Ключевая идея: Журнал (Log)
Тема "user_events" (журнал):
+-------------+-------------+-------------+-------------+
| Сообщение 0 | Сообщение 1 | Сообщение 2 | Сообщение 3 | ...
+-------------+-------------+-------------+-------------+
Offset: 0 1 2 3Свойства журнала:
| Свойство | Значение |
|---|---|
| Упорядоченность | Сообщения имеют порядок (offset) |
| Неизменяемость | Нельзя изменить или удалить сообщение |
| Хранение | Сообщения хранятся определённое время |
| Replay | Можно перечитать сообщения с любого места |
В отличие от очередей (RabbitMQ), где сообщение удаляется после прочтения, в Kafka сообщение остаётся в журнале. Несколько потребителей могут читать одно и то же сообщение независимо.
Основные компоненты
graph TD
P[Продюсер] --> T[Топик]
T --> C[Партиция 0]
T --> D[Партиция 1]
T --> E[Партиция 2]
C --> CG[Consumer Group A]
D --> CG
E --> CG
Топик (Topic)
Topic — логический поток сообщений. Хорошее название topic должно отражать смысл потока, а не внутреннее имя сервиса. Категория или канал, куда публикуются сообщения. Аналог таблицы в базе данных.
Плохое наименование:
request-topic
service-a-eventsХорошее наименование:
termination-request-events
contract-status-events
payment-eventsПартиция (Partition)
Topic физически разбивается на partitions. Partition — это упорядоченный журнал сообщений. Именно partition дает Kafka параллелизм и масштабирование.
| Характеристика | Значение |
|---|---|
| Порядок | Гарантирован внутри партиции |
| Параллелизм | Разные партиции могут читаться параллельно |
| Количество | Определяет максимальную степень параллелизма |
termination-request-events
partition 0: offset 0, 1, 2...
partition 1: offset 0, 1, 2...
partition 2: offset 0, 1, 2...Главное правило: порядок гарантируется только внутри одной partition. Между partitions глобального порядка нет.
Offset (Смещение)
Offset — позиция сообщения внутри partition. Он уникален только в рамках конкретной partition. Последовательное целое число.
Партиция 0:
offset 0: {user_id: 123, action: "login"}
offset 1: {user_id: 123, action: "search"}
offset 2: {user_id: 456, action: "login"}Продюсер (Producer)
Producer публикует сообщения. Он определяет topic, key, value, headers и уровень подтверждения записи. Producer не должен отправлять “просто JSON”. Он публикует событие с бизнес-смыслом.
Выбор партиции:
| Стратегия | Как работает |
|---|---|
| Round-robin | По очереди во все партиции |
| По ключу | hash(key) % partitions — все сообщения с одним ключом попадают в одну партицию |
| Указана явно | Продюсер сам решает |
Пример события:
{
"eventId": "8d1ad25d-23a1-4d99-a3e9-07d22e93a8e1",
"eventType": "TerminationRequestCreated",
"eventVersion": 1,
"occurredAt": "2026-05-30T12:30:00Z",
"requestId": "TR-100500",
"contractId": "C-987654",
"status": "CREATED"
}Консьюмер (Consumer)
Читает сообщения из топика.
Consumer Group (Группа консьюмеров)
Consumer group — логический потребитель, который может состоять из нескольких экземпляров. Несколько консьюмеров объединяются в группу. Каждая партиция читается одним консьюмером из группы.
graph LR
P[Партиция 0] --> C1[Консьюмер 1]
P2[Партиция 1] --> C2[Консьюмер 2]
P3[Партиция 2] --> C2
Правила:
| Ситуация | Результат |
|---|---|
| Партиций больше, чем консьюмеров | Некоторые консьюмеры читают несколько партиций |
| Консьюмеров больше, чем партиций | Лишние консьюмеры простаивают |
Брокер (Broker), leader, replica
Broker — сервер Kafka, который хранит партиции и обслуживает запросы. Kafka cluster состоит из нескольких brokers. Для каждой partition один broker является leader, остальные — replicas/followers.
Producer пишет в leader. Followers копируют данные с leader. Если leader падает, Kafka выбирает нового leader из актуальных replicas.
Кластер
Несколько брокеров образуют кластер. Один брокер — лидер (leader) партиции, другие — реплики (followers).
graph TD
subgraph "Кластер Kafka"
B1[Брокер 1<br>Лидер партиции 0]
B2[Брокер 2<br>Лидер партиции 1<br>Реплика партиции 0]
B3[Брокер 3<br>Лидер партиции 2<br>Реплика партиции 1]
end
Controller
Один из брокеров выполняет роль контроллера: управляет лидерами партиций, обрабатывает отказы.
Порядок сообщений
| Уровень | Гарантия |
|---|---|
| Внутри партиции | Строгий порядок (offset) |
| Между партициями | Порядок не гарантирован |
| Глобальный порядок | Только если партиция одна (не масштабируется) |
Как гарантировать порядок для одного пользователя: использовать user_id как ключ → все события пользователя в одной партиции.
Хранение данных
Retention (Срок хранения)
| Параметр | Значение по умолчанию |
|---|---|
| По времени | 7 дней |
| По объёму | 1 ГБ на партицию |
После истечения срока или превышения объёма старые сообщения удаляются.
Сегменты
Лог разбивается на сегменты (обычно 1 ГБ). Активный сегмент — тот, куда пишутся новые сообщения. Запечатанные сегменты доступны только для чтения и удаляются при устаревании.
Репликация
graph LR
L[Лидер] --> F1[Реплика 1]
L --> F2[Реплика 2]
Параметры репликации:
| Параметр | Значение |
|---|---|
replication.factor | Количество копий (обычно 3) |
min.insync.replicas | Минимум реплик, которые должны подтвердить запись |
ACKS (подтверждения):
| acks | Гарантия |
|---|---|
| 0 | Сообщение может потеряться |
| 1 | Лидер подтвердил (может потеряться, если лидер упал до репликации) |
| all | Все реплики в ISR подтвердили |
ISR (In-Sync Replicas)
ISR — In-Sync Replicas, актуальные реплики, которые успевают за leader. Если replica отстает, она может быть исключена из ISR.
Реплика в ISR:
- replication lag < параметры
- zookeeper connection aliveЕсли реплика отстала, она исключается из ISR. Запись считается успешной, если подтвердили все реплики из ISR.
ZooKeeper / KRaft
ZooKeeper (классическая)
Координирует кластер: хранит метаданные, выбирает контроллера, отслеживает состояние брокеров.
Недостатки: ZooKeeper — отдельная система, требует администрирования, не очень быстрая.
KRaft (Kafka Raft)
Начиная с версии 2.8, Kafka может работать без ZooKeeper. Контроллеры управляют метаданными через Raft-консенсус.
Преимущества: Проще администрирование, быстрее, масштабируемость до миллионов партиций.
Producer и Consumer в деталях
Продюсер (Producer)
Компоненты:
- Serializer: объект → байты
- Partitioner: определяет партицию
- Compressor: сжатие (gzip, snappy, lz4, zstd)
- Buffer: накопление сообщений перед отправкойКонсьюмер (Consumer)
Компоненты:
- Deserializer: байты → объект
- Commit offset: сохранение позиции
- Rebalance listener: реакция на перераспределение партицийConsumer Group Rebalance
При добавлении/удалении консьюмера партиции перераспределяются. Во время ребаланса консьюмеры не читают.
Потоковая обработка (Kafka Streams)
Kafka Streams — библиотека для обработки потоков данных внутри Kafka.
graph LR
A[Входной топик] --> B[Kafka Streams]
B --> C[Выходной топик]
Возможности:
- Фильтрация, маппинг
- Агрегации по окнам
- Join потоков
- Stateful обработка (хранит состояние в RocksDB)
Когда Kafka — хороший выбор
| Сценарий | Почему |
|---|---|
| Высокая нагрузка | Миллионы сообщений в секунду |
| Важен порядок | Гарантия внутри партиции |
| Хранение истории | Retention, replay |
| Много подписчиков | Каждый читает независимо |
| Потоковая обработка | Kafka Streams, ksqlDB |
Когда Kafka — не лучший выбор
| Сценарий | Почему |
|---|---|
| Нужна очередь с гарантией однократной доставки | Kafka не удаляет сообщения |
| Мало сообщений (<1000/сек) | Избыточно, RabbitMQ проще |
| Сложная маршрутизация | RabbitMQ гибче |
| Задержка важнее пропускной способности | Kafka оптимизирована на throughput, не latency |
Резюме
Apache Kafka — распределённый журнал (log), а не очередь. Сообщения не удаляются после прочтения.
Топик разбивается на партиции. Порядок гарантирован внутри партиции.
Продюсер пишет в партиции (round-robin или по ключу).
Консьюмеры объединяются в группы. Одна партиция — одному консьюмеру в группе.
Брокеры образуют кластер. Репликация обеспечивает надёжность.
ISR (In-Sync Replicas) — реплики, которые успевают за лидером.
ZooKeeper / KRaft — координация кластера.