Learning Platform
Глоссарий Troubleshooting
Урок 12.03 · 22 мин
Начальный
kafkatopicspartitionsconsumersoffsets

В прошлом уроке мы разобрались со Spark — distributed engine для обработки. Но для streaming-сценариев одного Spark недостаточно: нужна система доставки сообщений между сервисами и обработчиками. Самая популярная такая система в мире DE — Apache Kafka.

Kafka родилась в LinkedIn в 2010 году как решение проблемы передачи логов между сервисами. К 2014 году стала open-source в Apache, и сегодня её используют практически все крупные компании, работающие с реальным временем: Netflix, Spotify, Uber, Airbnb, Tesla, банки, маркетплейсы.

Этот урок даёт концептуальный обзор. Мы НЕ погружаемся в репликацию, internals брокера, KRaft, Schema Registry, Kafka Connect, security, tuning. Для глубины есть отдельный kafka-course на платформе.

Что такое Kafka на одной странице

Kafka — это распределённый append-only лог сообщений. Сообщения упорядочены, разбиты на партиции, реплицированы для надёжности. Producers пишут сообщения, consumers читают.

Это не очередь (как RabbitMQ или AWS SQS), это лог. Разница важна:

  • Очередь — сообщение прочитал -> оно удалено.
  • Лог — сообщения хранятся независимо от чтений, разные consumers могут читать одни и те же сообщения, можно перечитать с начала.

Это свойство (replayability) делает Kafka backbone-ом streaming-архитектур.

Архитектура Kafka: producers, brokers, consumers

Producers пишут в topic, broker сохраняет в партициях, consumers читают независимо, каждый со своим offset.

Producer Aorders serviceСервис заказов отправляет события каждый раз, когда оформляется новый заказ.
Kafka clusterbrokersРаспределённая система брокеров (узлов). Хранит сообщения в партициях, реплицирует между узлами для надёжности.
Consumer 1DWH loaderСтримит события в Snowflake для аналитики.
Producer Bcheckout serviceДругой сервис, который тоже пишет в Kafka.
TopicordersЛогический канал сообщений. Один topic = одна тема. Сообщения в topic разбиты на партиции.
Consumer 2fraud detectorАнализирует события на фрод в реальном времени. Параллельно с DWH loader читает те же события.
Producer Cmobile appЕщё один источник — мобильное приложение.
Consumer 3recommendation engineТретий потребитель — движок рекомендаций, обновляющий состояние по событиям.

Один поток событий -> несколько независимых обработчиков. Каждый идёт своим темпом, ничего не блокирует.

Topics

Topic — это логический канал сообщений. Например:

  • orders — события создания/обновления заказов.
  • user-clicks — клики пользователей на сайте.
  • payments — события платежей.
  • metrics.cpu — телеметрия CPU с серверов.

Сообщения публикуются в topic. Producers пишут в topic, consumers читают из topic. Один Kafka-кластер обычно держит сотни или тысячи topics для разных типов событий разных команд.

Partitions

Внутри topic есть partitions — упорядоченные последовательности сообщений. Каждый topic разбит на несколько партиций (например, 12 или 50 или 100), и партиции распределены по брокерам.

topic: orders
├── partition 0  -> broker 1 (leader), broker 2 (replica), broker 3 (replica)
├── partition 1  -> broker 2 (leader), broker 3 (replica), broker 1 (replica)
├── partition 2  -> broker 3 (leader), broker 1 (replica), broker 2 (replica)
└── ...

Внутри партиции сообщения строго упорядочены. Между партициями порядок не гарантируется.

Когда producer пишет сообщение, он выбирает партицию двумя способами:

  • По ключуpartition = hash(key) mod partition_count. Все сообщения с одинаковым ключом попадают в одну партицию, и потому идут в строгом порядке. Это используется для бизнес-сценариев типа «все события одного user_id обрабатываются в порядке».
  • Round-robin — без ключа партиции выбираются равномерно. Это даёт максимальный параллелизм, но теряет порядок.
NOTE

Партиционирование — это и масштабирование, и порядок одновременно. Больше партиций = больше параллелизма consumers. Партиция по ключу = строгий порядок для всех сообщений этого ключа. Эти две цели иногда конфликтуют — приходится их балансировать.

Offsets

Каждое сообщение внутри партиции имеет offset — последовательный номер от 0. Это позиция сообщения в логе.

partition 0:
  offset 0:  {user: A, event: click}
  offset 1:  {user: B, event: purchase}
  offset 2:  {user: A, event: click}
  offset 3:  {user: C, event: view}
  ...

Consumer хранит, до какого offset он дочитал в каждой партиции. Это и есть позиция чтения. Если consumer упал и перезапустился — он продолжает с последнего сохранённого offset, ничего не пропустив. Если нужно перечитать историю — можно сбросить offset на 0 и пройти лог заново.

Offset управляется одним из двух способов:

  • Commit’ы в Kafka. Consumer периодически коммитит offset в специальный internal topic __consumer_offsets. Kafka хранит, на каком offset стоит consumer group.
  • External tracking. Consumer сохраняет offset во внешнем хранилище — например, в DWH или в файл. Это даёт более гибкий контроль (например, atomic commit вместе с записью в DWH).

Producers

Producer — это код, который пишет сообщения в Kafka. Пример на Python:

from confluent_kafka import Producer

producer = Producer({'bootstrap.servers': 'kafka-broker:9092'})

producer.produce(
    topic='orders',
    key=str(user_id),                    # ключ для партиционирования
    value=json.dumps({                   # тело сообщения
        'order_id': 12345,
        'user_id': user_id,
        'amount': 99.50,
        'created_at': '2026-05-17T14:23:00Z'
    })
)

producer.flush()

Producer обычно живёт внутри другого сервиса (например, сервиса заказов или mobile app backend). Он работает асинхронно: сообщение публикуется в фоновый буфер, отправляется в Kafka, на ack обновляется метрика. Если broker недоступен, producer ретраит.

Consumers и consumer groups

Consumer — это код, который читает сообщения. Пример на Python:

from confluent_kafka import Consumer

consumer = Consumer({
    'bootstrap.servers': 'kafka-broker:9092',
    'group.id': 'dwh-loader',           # consumer group
    'auto.offset.reset': 'earliest'     # с какого offset начинать, если ничего не закоммичено
})

consumer.subscribe(['orders'])

while True:
    msg = consumer.poll(timeout=1.0)
    if msg is None:
        continue
    if msg.error():
        print(f"Error: {msg.error()}")
        continue
    process_order(json.loads(msg.value()))
    consumer.commit(asynchronous=False)

Самое важное здесь — consumer group. Это группа consumer-процессов, которые разделяют работу по одному topic.

Consumer groups: распределение партиций

Внутри одной consumer group партиции делятся между процессами. Между разными группами — независимое чтение.

topic orders6 partitionsTopic orders разбит на 6 партиций. Это даёт параллелизм.
Group Adwh-loaderГруппа A: 3 consumer-процесса, обрабатывают partitions [0,1,2,3,4,5]. Каждому досталось 2 партиции.
consumer A1partitions 0, 1Один процесс группы A читает партиции 0 и 1.
consumer A2partitions 2, 3
consumer A3partitions 4, 5
Group Bfraud-detectorГруппа B: независимо от группы A читает те же партиции. У группы B свой offset, она ничего не знает о группе A.
consumer B1partitions 0..2
consumer B2partitions 3..5

Ключевые свойства consumer groups:

  • Внутри группы партиции делятся между consumer-ами. Если в группе N consumers и в topic M партиций — каждому достанется M/N партиций.
  • Между группами чтение независимо. Каждая группа имеет свой offset, читает один и тот же поток событий своим темпом.
  • Авто-rebalance: если один consumer упал, оставшиеся в группе подхватывают его партиции.

Если consumers больше, чем партиций — лишние простаивают. Поэтому количество партиций определяет максимальный параллелизм потребления.

Replication

Kafka реплицирует партиции для надёжности. Каждая партиция имеет leader (брокер, через которого идёт read/write) и followers (реплики). Если leader падает, один из followers становится новым leader-ом.

Параметр replication.factor (обычно 3) означает, что каждое сообщение хранится на 3 брокерах. Если 2 упадут одновременно, данные не потеряются. В облачных managed-сервисах (Confluent Cloud, AWS MSK) replication настроен по умолчанию.

Простой пример: producer пишет, consumer читает

Соберём всё в один сценарий. Есть topic user-clicks, сервис сайта пишет события клика, downstream consumer считает количество кликов по странам.

Producer (на сайте, JS-backend):

producer.produce(
    topic='user-clicks',
    key=str(user_id),
    value=json.dumps({
        'user_id': user_id,
        'country': 'RU',
        'page': '/products/42',
        'timestamp': '2026-05-17T14:23:00Z'
    })
)

Consumer (отдельный сервис аналитики):

from collections import defaultdict
counts = defaultdict(int)

while True:
    msg = consumer.poll(1.0)
    if msg is None: continue
    event = json.loads(msg.value())
    counts[event['country']] += 1
    if total_processed % 1000 == 0:
        print(counts)
        consumer.commit()

Этот consumer вечно крутится и подсчитывает события. При перезапуске продолжает с последнего commit. Не теряет события (at-least-once), но может обработать одно событие дважды при сбое (нужен idempotent processing для exactly-once).

Где Kafka в DE-стеке

Kafka типично занимает позицию backbone для streaming:

  • Source ingestion. События приложений, IoT-датчики, CDC из OLTP-баз (через Debezium) пишутся в Kafka.
  • Stream processing. Flink, Spark Structured Streaming, Kafka Streams читают Kafka, обрабатывают, пишут в другие topics или sinks.
  • DWH ingestion. Kafka Connect, Snowflake Kafka Connector, BigQuery Subscriber льют события в DWH.
  • Operational decoupling. Сервисы общаются через Kafka, не зная друг о друге напрямую — event-driven architecture.

Что осталось за кадром

Глубокая Kafka — это:

  • KRaft и ZooKeeper-less архитектура. Современная Kafka не требует ZooKeeper для координации.
  • Schema Registry и Avro. Управление схемами сообщений и обратной совместимостью.
  • Exactly-once семантика. Транзакции Kafka, idempotent producers.
  • Kafka Connect. Готовые connectors к десяткам источников и sinks.
  • Tiered storage. Холодные данные на S3, горячие на брокерах.
  • Security. SASL, mTLS, ACL.
  • Tuning. Размер сообщений, batch.size, compression, num.partitions, replication.factor.

В нашем kafka-course на платформе мы разбираем это с диаграммами и hands-on lab-ом. Если планируешь работать со streaming серьёзно — обязательно туда.

Kafka internals: distributed commit log, партиции и репликация Debezium: CDC из OLTP в Kafka без кода
TIP

Базовое понимание Kafka — обязательный навык для middle/senior DE. На собеседованиях часто спрашивают partitions, consumer groups, offset management и схему replication. Это не глубокие internals, но обязательный концептуальный минимум.

Попробуй сам

Подумай о приложении, которое ты знаешь — мессенджер, банк, маркетплейс. Какие топики в нём могли бы быть? messages, user-actions, payments, notifications? Какие consumers читают каждый топик? notification-service, dwh-loader, fraud-detector, analytics? Это упражнение даёт почувствовать роль Kafka — она склеивает десятки независимых сервисов через единый поток событий.

Проверка знанийKnowledge check
Какая разница между Kafka и обычной очередью сообщений типа RabbitMQ?
ОтветAnswer
Очередь (RabbitMQ, SQS) работает по принципу «прочитал — удалил»: каждое сообщение доставляется одному потребителю и исчезает. Kafka — это append-only лог: сообщения хранятся независимо от чтений, разные consumer groups могут читать один и тот же поток независимо со своим offset, можно перечитать историю с любой точки (replay). Это свойство критично для streaming-архитектур: один источник событий обрабатывается несколькими независимыми обработчиками (DWH loader, fraud detector, recommendations), и каждый идёт своим темпом. Replay позволяет делать backfill через переподписку с offset 0 — это основа Kappa Architecture.

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

Результат: 0 из 0
Концептуальный
Вопрос 1 из 5. Какая принципиальная разница между Kafka и очередью сообщений типа RabbitMQ?

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

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

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

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