Открыть сервис

Structured Streaming

Structured Streaming — это масштабируемый и отказоустойчивый движок потоковой обработки данных, встроенный в Apache Spark (начиная с версии 2.0, выпущенной в 2016 году). Он позволяет обрабатывать потоки данных в реальном времени, используя тот же высокоуровневый API DataFrames и Dataset, что и для пакетных вычислений, реализуя парадигму «непрерывных приложений» (continuous applications). Ключевая особенность — представление непрерывного потока ввходящих данных как бесконечно растущей таблицы, к которой применяются реляционные операции (фильтрация, агрегация, соединения) по принципу микропакетной обработки (micro-batch processing) или, начиная с Spark 2.3, непрерывной обработки (continuous processing).

История и предпосылки

До появления Structured Streaming обработка потоков в Apache Spark была возможна через более низкоуровневый API — Spark Streaming (DStreams), основанный на дискретизированных потоках (Discretized Streams). Этот подход имел ряд ограничений: сложность в сочетании с пакетными операциями, проблемы с гарантиями «ровно один раз» (exactly-once semantics) и трудоёмкость поддержания состояния. Structured Streaming был разработан в 2015–2016 годах командой инженеров Databricks (в первую очередь Михаилом Армянским и Татхой Кристианом) как попытка унифицировать пакетную и потоковую обработку.

Концепция была впервые представлена широкой публике в 2016 году на конференции Spark Summit. К 2018 году, с выходом Apache Spark 2.3, была добавлена экспериментальная поддержка непрерывной обработки, обеспечивающая субмиллисекундные задержки. С 2019 года (Spark 2.4 и 3.0) Structured Streaming стал основным и рекомендуемым инструментом потоковой обработки в экосистеме Apache Spark.

Архитектура и принципы работы

Модель «поток как таблица»

В основе Structured Streaming лежит метафора «бесконечной таблицы». Каждый новый пакет данных (микропакет) или каждое новое событие (в режиме непрерывной обработки) интерпретируется как новая строка, добавляемая в эту таблицу. Пользователь задаёт запрос в терминах DataFrames или Dataset (например, spark.readStream().table("input").groupBy("key").count()), который выполняется инкрементально: результирующая таблица пересчитывается при добавлении новых данных.

Ключевое следствие такого подхода — логический план выполнения запроса (query plan) одинаков для потокового и пакетного сценариев. Это позволяет легко переключаться между ними, меняя только метод чтения и записи.

Режимы вывода (Output Modes)

Движок поддерживает три основных режима, определяющих, какие именно изменения в результирующей таблице будут записаны в выходной поток (sink):

Семантика обработки (Exactly-Once)

Одно из главных достижений Structured Streaming — гарантия «ровно один раз» (exactly-once) для всех поддерживаемых источников и приёмников, при условии их идемпотентности и транзакционности. Это достигается за счёт:

Управление состоянием (State Management)

Для обработки событий, которые могут прийти с задержкой или в неправильном порядке, используется концепция водяного знака (watermark). Водяной знак — это временная граница, определяющая, до какого момента данные считаются «актуальными». Данные, поступившие позже водяного знака, отбрасываются или учитываются с пометкой опоздавших. Пользователь задаёт водяной знак в определении окна агрегации.

Движок поддерживает произвольные состояния (arbitrary stateful operations) через интерфейс mapGroupsWithState() и flatMapGroupsWithState(), позволяя реализовать сложную логику, например, обнаружение аномалий или поддержание сессий.

Применение

Structured Streaming применяется в задачах, требующих обработки непрерывных потоков данных:

Интеграция с источниками и приёмниками

Structured Streaming поддерживает множество источников (sources) и приёмников (sinks):

Ограничения и критика

Несмотря на широкое распространение, Structured Streaming имеет ряд ограничений:

Пример (без кода)

Типичный конвейер может выглядеть так: приложение получает поток событий от пользовательских кликов из Apache Kafka, фильтрует только события, содержащие покупки, группирует их по идентификатору товара в окне длительностью 5 минут и записывает результат в Amazon S3 в формате Parquet для последующего анализа в Amazon Athena или Databricks SQL. Все эти операции выполняются с гарантией «ровно один раз» и автоматической отказоустойчивостью при перезапуске из контрольной точки.

Источники

  1. Документация Apache Spark: «Structured Streaming Programming Guide».
  2. Armbrust, M., Das, T., Torres, J., et al. (2018). «Structured Streaming: A Declarative API for Real-Time Applications in Apache Spark». Proceedings of the 2018 International Conference on Management of Data (SIGMOD).
  3. Apache Spark официальный репозиторий на GitHub — раздел «sql/core/src/main/scala/org/apache/spark/sql/execution/streaming».
  4. Дастумы основных пакетов Databricks: «Best Practices for Streaming with Delta Lake».
  5. Книга: Chambers, B., Zaharia, M. (2018). «Spark: The Definitive Guide». O'Reilly Media (Глава 13–15).

BFOmetr — база данных и аналитика по компаниям России.

На главную BFOmetr →