Kafka Streams
Kafka Streams — это клиентская библиотека для построения приложений и микросервисов, обрабатывающих данные в реальном времени, входящая в экосистему Apache Kafka. Библиотека позволяет реализовывать потоковую обработку (stream processing) непосредственно на стороне приложения, без необходимости развёртывания отдельного кластера для обработки (например, Apache Flink или Apache Spark Streaming). Kafka Streams использует топики Apache Kafka как источник входных данных и как приёмник результатов, предоставляя высокоуровневый DSL (Domain-Specific Language) и низкоуровневый процессорный API для преобразования, агрегации и объединения потоков.
История и предпосылки создания
Библиотека Kafka Streams была впервые представлена в составе Apache Kafka версии 0.10.0.0, выпущенной в мае 2016 года. До её появления для организации потоковой обработки данных из Kafka разработчики были вынуждены использовать внешние фреймворки, такие как Apache Storm, Apache Spark Streaming или Apache Flink, которые требовали развёртывания и администрирования отдельной инфраструктуры. Основной целью создания Kafka Streams было предоставление лёгкого, встраиваемого решения, которое могло бы работать как часть обычного Java-приложения, используя те же механизмы отказоустойчивости и масштабирования, что и сам брокер Kafka (через группы потребителей и ребалансировку разделов).
Архитектура и ключевые концепции
Топология и процессоры
Приложение Kafka Streams строится на понятии топологии (topology) — ориентированного графа, узлами которого являются процессоры (processor), а рёбрами — потоки данных. Различают два типа процессоров:
- Source Processor — процессор, который получает данные из одного или нескольких исходных топиков Kafka.
- Sink Processor — процессор, который отправляет результаты обработки в целевые топики Kafka.
Промежуточные процессоры могут выполнять любые операции: фильтрацию, преобразование, агрегацию, соединение (join) потоков и таблиц.
Потоки и таблицы
Kafka Streams оперирует двумя абстракциями:
- KStream — это неограниченный поток записей (ключ-значение), где каждая запись интерпретируется как независимое событие. Операции над KStream (например, map, filter) применяются к каждой записи по отдельности.
- KTable — это изменяемая таблица (чанжлог), где каждая новая запись с тем же ключом перезаписывает предыдущее значение. KTable представляет собой материализованное представление данных, хранящееся в локальном хранилище (RocksDB) и реплицируемое в топик Kafka для отказоустойчивости. KTable позволяет выполнять операции типа «просмотр» (lookup) и агрегации с сохранением состояния.
Также существует GlobalKTable — полностью реплицированная таблица, которая копируется на все узлы приложения целиком, что позволяет выполнять соединения без перераспределения данных.
Состояние и хранилище
Для операций, требующих запоминания промежуточных данных (агрегации, оконные операции, соединения), Kafka Streams использует управляемое состояние (state store). По умолчанию состояние хранится на локальном диске с помощью встраиваемой базы данных RocksDB. Для отказоустойчивости каждое локальное хранилище реплицируется в отдельный топик Kafka (чанжлог-топик), что позволяет восстановить состояние после сбоя узла. Разработчик может также использовать собственные реализации хранилища (например, in-memory или на основе других БД).
Обработка времени и окна
Kafka Streams поддерживает три типа времени для записей:
- Event time — время, установленное самим продюсером в записи.
- Processing time — время обработки записи на стороне приложения.
- Ingestion time — время, когда запись была добавлена в топик брокером.
Для агрегации и соединений библиотека предоставляет механизмы оконной обработки:
- Tumbling window — непересекающиеся окна фиксированной длины.
- Hopping window — перекрывающиеся окна фиксированной длины.
- Sliding window — окна, которые открываются для каждой записи на заданный интервал времени (используется для соединений).
- Session window — окна, которые объединяют записи по ключу, если между ними нет паузы длиннее заданного интервала (полезно для анализа сессий пользователей).
API
High-Level Streams DSL
DSL-уровень предоставляет набор высокоуровневых операторов, похожих на функции из функционального программирования: map, filter, flatMap, groupBy, aggregate, reduce, join, leftJoin, outerJoin и другие. Эти операторы работают с абстракциями KStream, KTable и GlobalKTable. DSL также включает поддержку оконных операций и материализации промежуточных результатов в таблицы.
Low-Level Processor API
Processor API позволяет разработчику создавать собственные процессоры, реализуя интерфейс Processor или наследуясь от класса AbstractProcessor. В этом API можно напрямую управлять состоянием, планировать периодические задачи (punctuator) и выполнять низкоуровневые манипуляции с записями. Processor API используется, когда логика обработки не укладывается в рамки DSL, например, для сложных преобразований с произвольным управлением состоянием.
Масштабирование и отказоустойчивость
Масштабирование приложения Kafka Streams достигается за счёт увеличения числа экземпляров приложения (процессов) в рамках одной группы потребителей. Каждый экземпляр обрабатывает подмножество разделов (partitions) входных топиков. При добавлении или удалении экземпляра происходит ребалансировка разделов между всеми участниками группы. Для сохранения порядка обработки внутри раздела все записи с одним ключом попадают в один и тот же раздел и обрабатываются одним экземпляром.
Отказоустойчивость обеспечивается за счёт:
- Репликации состояния в топики Kafka.
- Автоматического перераспределения разделов при сбое экземпляра.
- Использования идемпотентных продюсеров и транзакций (начиная с Kafka 0.11) для обеспечения exactly-once семантики.
Применение
Kafka Streams используется в сценариях, где требуется обработка данных в реальном времени с низкой задержкой и высокой пропускной способностью. Типичные примеры:
- Аналитика в реальном времени (подсчёт метрик, обнаружение аномалий).
- Обогащение потоков данных (соединение потока событий с таблицей справочных данных).
- Трансформация и маршрутизация сообщений (ETL-процессы).
- Построение событийно-ориентированных микросервисов.
Библиотека активно используется в таких компаниях, как LinkedIn, Netflix, Uber, Pinterest, а также в ряде российских компаний, занимающихся обработкой больших данных и построением data-платформ.
Критика и ограничения
Несмотря на популярность, Kafka Streams имеет ряд ограничений:
- Привязка к JVM: библиотека написана на Java и Scala, что ограничивает её использование в экосистемах других языков (существуют обёртки для Python и Go, но они не обладают полной функциональностью).
- Сложность отладки: распределённая природа и работа с состоянием могут затруднять отладку и профилирование.
- Управление состоянием: по умолчанию используется RocksDB, которая может потреблять значительные ресурсы памяти и диска; настройка её параметров требует опыта.
- Отсутствие встроенного управления потоками (backpressure): библиотека полагается на механизмы Kafka (например, настройки
max.poll.recordsиfetch.max.bytes), что не всегда эффективно при резких всплесках нагрузки.
Сравнение с альтернативами
| Характеристика | Kafka Streams | Apache Flink | Apache Spark Streaming |
|---|---|---|---|
| Архитектура | Встраиваемая библиотека | Отдельный кластер | Отдельный кластер |
| Модель обработки | Record-at-a-time | Record-at-a-time | Micro-batch |
| Exactly-once семантика | Поддерживается (через транзакции Kafka) | Поддерживается | Поддерживается |
| Управление состоянием | RocksDB + Kafka changelog | Managed state (RocksDB, FS) | Stateful DStreams / Structured Streaming |
| Развёртывание | Как часть приложения | Требуется Flink-кластер | Требуется Spark-кластер |
Интересные факты
- Kafka Streams является частью проекта Apache Kafka и распространяется под лицензией Apache 2.0.
- Библиотека активно развивается; начиная с версии 2.0 в неё добавлена поддержка интерактивных запросов (Interactive Queries), позволяющих напрямую обращаться к локальному состоянию приложения через REST-интерфейс.
- В версии 2.8 появилась поддержка KTable-KTable foreign-key joins, что расширило возможности соединения таблиц по произвольным полям.
Источники
- Apache Kafka Documentation. Kafka Streams Architecture.
- Confluent Documentation. Kafka Streams Concepts.
- Bill Bejeck. «Kafka Streams in Action». Manning Publications, 2018.
- Neha Narkhede, Gwen Shapira, Todd Palino. «Kafka: The Definitive Guide». O'Reilly Media, 2017.
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →