офлайн
офлайн
ГлавнаяApache Kafka.md
---
tags: [microservices, kafka]
created: 2026-11-06
updated: 
---

Apache Kafka

Содержание

› Базовые концепции и Архитектура

Apache Kafka — это распределенная платформа потоковой передачи событий (Distributed Event Streaming Platform). В отличие от классических брокеров сообщений (RabbitMQ), Kafka реализует паттерн “Глупый брокер — умный клиент”. Брокер просто пишет данные на диск (Append-only log) и не удаляет их после прочтения. Клиенты (Consumers) сами вытягивают данные (Pull) и отслеживают свой прогресс.

Основные сущности:

  • Broker (Брокер): Отдельный сервер (узел) в кластере Kafka.
  • Topic (Топик): Логическая категория (имя канала), куда отправляются сообщения.
  • Partition (Партиция): Физическое разделение топика. Представляет собой неизменяемый файл на диске брокера. Обеспечивает горизональное масштабирование (нагрузка распределяется по брокерам).
  • Offset (Оффсет): Уникальный, неизменяемый порядковый номер сообщения строго внутри одной партиции.
  • Segment (Сегмент): Физический файл, на которые разбивается партиция (по умолчанию 1 ГБ). Запись идет только в активный сегмент. Старые сегменты используются только для чтения и последующего удаления.

Гарантия порядка: Kafka гарантирует строгий порядок сообщений (FIFO) только в рамках одной партиции. В рамках всего топика порядка нет.

Координация кластера (Zookeeper vs KRaft)

Для управления распределенным кластером (отслеживание живых брокеров, выбор Лидеров партиций, хранение метаданных) Kafka требуется механизм координации.

  • Zookeeper (Устаревший подход): Внешняя распределенная система. Один из брокеров Kafka назначался Контроллером и общался с Zookeeper. Минусы: сложность администрирования двух разных систем, проблемы с производительностью при сотнях тысяч партиций.
  • KRaft (Kafka Raft - Современный подход): Начиная с версии 3.3, Kafka работает без Zookeeper. Метаданные кластера хранятся внутри самой Kafka в специальном топике __cluster_metadata.
    • Брокеры могут иметь роль Broker (хранение данных) и/или Controller (управление кластером через алгоритм консенсуса Raft).
    • Плюсы: Упрощение архитектуры, поддержка миллионов партиций, мгновенное восстановление после сбоев.

› Структура сообщения (Record)

Сообщение в Kafka — это массив байтов, состоящий из:

  1. Headers: Метаданные (ключ-значение).
  2. Timestamp: Время создания.
  3. Key (Ключ): Опциональное поле, критически важное для маршрутизации.
  4. Value (Значение): Тело сообщения (Payload).

› Producers (Продюсеры) и Маршрутизация

Продюсер отправляет данные в кластер. Выбор партиции для записи зависит от ключа:

  • Key == null: Используется алгоритм Round-Robin. Сообщения равномерно распределяются по всем партициям. Идеальная балансировка, но порядок не гарантируется.
  • Key != null: Используется хэширование (Hash(Key) % num_partitions). Все сообщения с одинаковым ключом всегда попадают в одну и ту же партицию. Это гарантирует строгий порядок обработки связанных событий (например, все статусы одного заказа).

Гарантии доставки (Acknowledgments - acks):

Параметр acks определяет, когда продюсер считает сообщение успешно отправленным:

  • acks = 0: Продюсер не ждет ответа. Максимальная пропускная способность, высокий риск потери данных.
  • acks = 1: Продюсер ждет подтверждения только от Лидера партиции. Риск потери данных, если Лидер упадет до репликации.
  • acks = all (или -1): Лидер ждет подтверждения записи от всех синхронизированных реплик (ISR). Максимальная надежность, минимальная скорость.

› Consumers (Консьюмеры) и Консьюмер-группы

Консьюмеры объединяются в Consumer Group (по параметру group.id) для распараллеливания чтения.

Правило масштабирования: Одну партицию может читать только один консьюмер из одной группы в единицу времени. (Partition <> Consumer == Many To One)

  • Если консьюмеров больше, чем партиций — “лишние” консьюмеры будут простаивать (Idle).
  • Rebalance (Ребалансировка): Процесс перераспределения партиций между консьюмерами при добавлении нового консьюмера или падении существующего. Во время ребалансировки чтение приостанавливается (Stop-the-world).

Управление оффсетами (Offset Commit):

Консьюмер должен сообщать Kafka, какие сообщения он успешно обработал, сохраняя оффсет во внутренний топик __consumer_offsets.

  • enable.auto.commit = true: Kafka сама коммитит оффсеты в фоновом потоке раз в заданный интервал. Риск: Возможна потеря данных (At-most-once), если консьюмер упадет во время обработки, но после автокоммита.
  • enable.auto.commit = false: Разработчик вызывает commitSync() / commitAsync() вручную после успешной обработки бизнес-логики (например, записи в БД). Гарантирует, что данные не потеряются (At-least-once).

› Отказоустойчивость (Fault Tolerance)

Обеспечивается параметром Replication Factor (обычно = 3).

  • Каждая партиция имеет 1 Лидера (Leader) и N Ведомых (Followers).
  • Все операции чтения и записи идут только через Лидера.
  • Followers асинхронно копируют данные. Те, кто не отстает от Лидера, находятся в списке ISR (In-Sync Replicas).
  • При падении брокера-лидера, Kafka автоматически выбирает нового лидера из списка ISR.
  • Consumer может читать сообщение только после того, как его скопировали всe Followers.

› Очистка данных (Topic Cleanup)

Настраивается параметром cleanup.policy:

  1. delete (Удаление): Старые сегменты удаляются целиком при достижении лимита времени (retention.ms, по умолчанию 7 дней) или размера (retention.bytes).
  2. compact (Компактизация): Kafka периодически сканирует партицию и оставляет только самое последнее (актуальное) сообщение для каждого Ключа. Старые версии сообщений с тем же ключом удаляются. Идеально для хранения справочников и кэшей.

› Интеграция со Spring Boot (Spring Kafka)

Стартер spring-kafka предоставляет высокоуровневые абстракции для работы с брокером.

  • Отправка (Producer): Используется бин KafkaTemplate<K, V>. Берет на себя сериализацию объектов в байты и асинхронную отправку. Метод send(topic, key, value) возвращает CompletableFuture.
  • Чтение (Consumer): Используется аннотация @KafkaListener(topics = "...", groupId = "...") над методом. Spring создает фоновые потоки (Message Listener Containers), которые опрашивают брокер, десериализуют байты в Java-объекты и вызывают аннотированный метод.
  • Коммиты в Spring: По умолчанию Spring использует AckMode.BATCH (автоматически коммитит оффсет после успешного завершения метода @KafkaListener). Для ручного контроля используется AckMode.MANUAL, а в метод передается объект Acknowledgment, у которого нужно явно вызвать ack.acknowledge().
main48 заметок780 слов4 мин чтения