Learning Platform
Глоссарий Troubleshooting
Урок 02.02 · 25 мин
Средний
BrokersTopicsPartitionsLeaderFollower

Брокеры, Топики, Партиции

Первый урок дал ментальную модель — commit log. Теперь разберём физическую реальность: как этот commit log существует в кластере из нескольких машин. Ответ — через три уровня абстракции: брокеры, топики и партиции.


Брокер: JVM-процесс, хранящий данные

Брокер (broker) — это отдельный серверный процесс Kafka (JVM). Каждый брокер идентифицируется числовым node.id. В кластере брокеры взаимодействуют через KRaft-протокол (Kafka 4.0+).

Ключевые конфигурационные свойства брокера:

# node.id — уникальный числовой идентификатор в кластере
node.id=1

# process.roles — роль в кластере
# broker: обслуживает producers и consumers, хранит данные
# controller: участвует в KRaft quorum (metadata management)
# combined: и то и другое (типично для dev/small clusters)
process.roles=broker,controller

# listeners — адреса и протоколы
listeners=PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093
advertised.listeners=PLAINTEXT://broker1.example.com:9092

# log.dirs — где брокер хранит данные партиций
log.dirs=/var/kafka/logs

В production-кластере типично разделяют роли: 3 dedicated controller-узла + N broker-узлов. В Kafka 4.0 брокер с process.roles=broker не участвует в quorum — он только хранит данные и обслуживает клиентов. Контроллеры с process.roles=controller не хранят пользовательские данные.

NOTE

В Kafka 4.0 все конфигурационные файлы находятся в config/ (не в config/kraft/ как в Kafka 3.x). KRaft — единственный режим: KAFKA_ZOOKEEPER_CONNECT не существует как переменная среды в официальном образе apache/kafka:4.0.0.


Топик: именованный поток событий

Топик — это логическое пространство имён для событий одного типа. orders, payments, user-sessions, inventory-updates — всё это топики.

Создание топика через CLI:

# Kafka 4.0: только --bootstrap-server, не --zookeeper
kafka-topics.sh \
  --create \
  --topic orders \
  --partitions 6 \
  --replication-factor 3 \
  --bootstrap-server localhost:9092

Важнейшие параметры топика:

ПараметрЧто задаётТипичное значение
--partitionsСтепень параллелизма и масштаб хранения6–48 для production
--replication-factorСколько копий каждой партиции в кластере3 (не больше числа брокеров)
retention.msКак долго хранить данные604800000 (7 дней)
cleanup.policydelete (удаление по retention) или compact (дедупликация по ключу)delete

Просмотр конфигурации топика:

kafka-topics.sh \
  --describe \
  --topic orders \
  --bootstrap-server localhost:9092

Вывод покажет: PartitionCount, ReplicationFactor, лидеров и реплики каждой партиции, список ISR (In-Sync Replicas).


Партиция: единица параллелизма и упорядоченности

Партиция — физическая единица хранения и параллелизма. Топик orders с --partitions 6 создаёт шесть отдельных append-only логов: orders-0, orders-1, …, orders-5.

Три свойства партиций, которые нужно понять:

1. Упорядоченность внутри партиции. Kafka гарантирует порядок записей строго внутри одной партиции. Между партициями порядок не гарантирован. Если порядок важен, используйте ключ сообщения: продюсер хэширует ключ и всегда направляет сообщения с одинаковым ключом в одну партицию.

# Python kafka-python: все события одного order_id в одну партицию
producer.send(
    'orders',
    key=b'order-12345',   # ключ → deterministic partition
    value=b'{"status":"shipped"}'
)

2. Параллелизм потребления. Один consumer group может читать топик параллельно в N потоков, где N = количество партиций. Больше партиций = больше потенциальный параллелизм потребления. Но: каждую партицию читает ровно один consumer в группе. Если в группе 4 consumer, а партиций 6 — двое consumer читают по 2 партиции, двое — по 1.

3. Выбор числа партиций. Это одно из самых критичных решений при создании топика. Увеличить число партиций можно (kafka-topics.sh --alter), но уменьшить — нельзя. Правило: num.partitions >= max_consumers_in_group. Для высоконагруженных топиков: ориентируйтесь на целевую пропускную способность (MB/s) / пропускная способность одной партиции.

WARNING

Не создавайте слишком много партиций. Каждая партиция — это открытый файл на диске брокера, память в heap JVM, и overhead для leader election. Кластер из 3 брокеров с 50 000 партиций работает нестабильно. Ориентир: не более 4000 партиций на брокер (Kafka 4.0 с KRaft справляется лучше, чем ZooKeeper-эра, но физические ограничения остаются).


Лидер и Фолловер: распределение нагрузки

Каждая партиция имеет ровно одну лидерскую реплику (leader) и одну или несколько фолловерских реплик (follower).

Лидер принимает все записи от продюсеров и все запросы на чтение от потребителей (по умолчанию). Это единственный контакт продюсера и потребителя с партицией.

Фолловеры не взаимодействуют с клиентами напрямую. Их единственная задача — реплицировать данные от лидера через fetch-запросы. Как только фолловер получил запись и подтвердил её хранение, он входит в ISR (In-Sync Replicas) — множество реплик, которые могут стать новым лидером.

Kafka Cluster: Брокеры и Партиции
Controller 1KRaft-контроллер (узел 1): участвует в Raft-голосовании за лидера метаданных. Хранит лог метаданных кластера — топики, партиции, ISR-списки, конфигурации брокеров. Большинство (2 из 3) требуется для подтверждения записи в лог.
Controller 2KRaft-контроллер (узел 2): участник кворума метаданных. Реплицирует лог метаданных от активного контроллера. При отказе лидера участвует в новых выборах. process.roles=controller.
Controller 3KRaft-контроллер (узел 3): третий участник кворума. Обеспечивает нечётное число узлов для гарантированного большинства. Хранит полную копию лога метаданных. Заменяет ZooKeeper начиная с Kafka 3.3.
обновления метаданных
Broker 1Брокер 1 (node.id=1): сервер Kafka, принимающий записи от продюсеров и обслуживающий запросы чтения консьюмеров. Является лидером партиций P0 и P3 — только через лидера выполняются записи. process.roles=broker.
P0 (leader)Партиция P0, лидер на Broker 1: все записи продюсера поступают сюда. Брокер-лидер добавляет запись в локальный лог, затем фолловеры асинхронно реплицируют её. ISR = {B1, B2, B3}.
P3 (leader)Партиция P3, лидер на Broker 1: фолловеры на Broker 2 и Broker 3 тянут данные через FetchRequest. LEO лидера = смещение следующей записи. HW продвигается когда все ISR-реплики подтверждают получение.
P1 (follower)Партиция P1, фолловер на Broker 1: реплика в составе ISR. Периодически отправляет FetchRequest лидеру (Broker 2) для получения новых записей. При отставании более чем на replica.lag.time.max.ms исключается из ISR.
реплицирует
реплицирует
Broker 2Брокер 2 (node.id=2): участник кластера. Является лидером партиции P1, фолловером P0 и P3. Обрабатывает FetchRequest от фолловеров-реплик и от консьюмеров. Участвует в ISR всех партиций.
P1 (leader)Партиция P1, лидер на Broker 2: принимает записи продюсера для P1. Два фолловера (B1, B3) тянут данные через Fetch API. Когда оба подтвердили LEO, лидер продвигает High Watermark.
P0 (follower)Партиция P0, фолловер на Broker 2: синхронная реплика. Задержка репликации контролируется через JMX-метрику ReplicaLag. Если фолловер падает, контроллер убирает его из ISR без прерывания работы лидера.
P2 (follower)Партиция P2, фолловер на Broker 2: входит в ISR P2 (лидер — Broker 3). При failover лидера Broker 2 может быть выбран новым лидером, если находится в ISR на момент сбоя.
реплицирует
реплицирует
Broker 3Брокер 3 (node.id=3): третий узел кластера. Является лидером партиции P2, фолловером P1 и P3. Обеспечивает репликацию данных для отказоустойчивости. replication.factor=3 гарантирует, что каждая партиция существует на всех трёх брокерах.
P2 (leader)Партиция P2, лидер на Broker 3: обрабатывает все записи в P2. После получения подтверждений от ISR-фолловеров (B1, B2) продвигает HW и сообщает продюсеру об успешной записи (при acks=all).
P1 (follower)Партиция P1, фолловер на Broker 3: реплицирует P1 с Broker 2. Входит в ISR P1. При lag > replica.lag.time.max.ms (по умолчанию 30000 мс) контроллер исключает фолловера из ISR.
P3 (follower)Партиция P3, фолловер на Broker 3: реплицирует P3 с Broker 1. Консьюмеры читают данные только до High Watermark — отметки, до которой все ISR-реплики подтвердили получение записей.
High WatermarkHigh Watermark (HW): максимальное смещение, до которого все реплики в ISR подтвердили получение данных. HW = min(LEO по всем ISR-репликам). Консьюмеры могут читать только записи с offset < HW. Гарантирует, что прочитанные данные не будут потеряны при failover лидера.
LEO (Log End Offset)Log End Offset (LEO): смещение следующей записи, которая будет добавлена в лог данного брокера. LEO лидера всегда >= LEO фолловеров. Разница LEO(leader) - LEO(follower) называется replica lag. Мониторируется через kafka.server:type=ReplicaFetcherManager.

Назначение лидеров при создании топика: KRaft-контроллер распределяет лидеров равномерно по брокерам через preferred leader assignment. Топик с 6 партициями в кластере из 3 брокеров — каждый брокер становится лидером 2 партиций.

Проверить, кто является лидером каждой партиции:

kafka-topics.sh \
  --describe \
  --topic orders \
  --bootstrap-server localhost:9092

# Пример вывода:
# Topic: orders  PartitionCount: 6  ReplicationFactor: 3
# Topic: orders  Partition: 0  Leader: 1  Replicas: 1,2,3  Isr: 1,2,3
# Topic: orders  Partition: 1  Leader: 2  Replicas: 2,3,1  Isr: 2,3,1
# Topic: orders  Partition: 2  Leader: 3  Replicas: 3,1,2  Isr: 3,1,2
# ...

Replication Factor: сколько копий держать

--replication-factor 3 означает: каждая запись хранится на 3 брокерах — 1 лидер + 2 фолловера.

Replication factor напрямую влияет на:

  • Надёжность: при RF=3 кластер переживает потерю 2 брокеров (один за раз, с recovery между ними).
  • Пропускную способность записи: продюсер ждёт подтверждения от ISR-реплик (зависит от acks).
  • Использование дискового пространства: в 3 раза больше, чем при RF=1.
TIP

Минимально рекомендуемый RF для production: 3. RF=2 не рекомендуется — при потере одного брокера у вас только одна копия данных, и любая проблема с этим брокером приведёт к недоступности. RF=1 только для dev и test окружений.

Смотреть replication factor топика и текущих лидеров:

# Проверить баланс лидеров по брокерам
kafka-topics.sh \
  --describe \
  --topic orders \
  --bootstrap-server localhost:9092 \
  --report-under-replicated-partitions

# Если брокер упал — вывод покажет партиции без одной из реплик

Ключевые выводы

  1. Брокер — JVM-процесс с node.id, process.roles=broker|controller|broker,controller.
  2. Топик — именованный поток с num.partitions и replication.factor. CLI: kafka-topics.sh --bootstrap-server.
  3. Партиция — единица параллелизма и упорядоченности. Порядок гарантирован только внутри одной партиции.
  4. Лидер принимает записи и чтения. Фолловеры реплицируют через fetch.
  5. Replication factor = 3 для production. Изменение числа партиций — только увеличение, не уменьшение.
Проверка знанийKnowledge check
Топик `events` создан с num.partitions=6. Продюсер отправляет два события: первое с key='user-1', второе с key='user-2'. Consumer group с 3 потребителями читает этот топик. Какая гарантия порядка существует?
ОтветAnswer
Kafka гарантирует порядок только внутри одной партиции. Оба события с разными ключами попадут в разные партиции (ключ хэшируется в partition index). Порядок между ними не определён. Если нужен порядок событий для одного пользователя, используйте один и тот же ключ для всех его событий: key='user-1' всегда попадёт в одну и ту же партицию (хэш детерминирован), и все события user-1 будут упорядочены. При num.partitions=6 и 3 потребителях каждый читает по 2 партиции — полный параллелизм использован не будет (3 потребителя, 6 партиций — оптимально 6 потребителей).

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 4. Топик `user-events` создан с `num.partitions=4`. Consumer group `analytics` имеет 6 активных потребителей. Как Kafka распределит партиции между потребителями?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 6