Требования к современным системам в части скорости обработки информации растут. Пользователи уже не хотят ждать загрузки поста в социальной сети или фильма в онлайн-кинотеатре дольше нескольких секунд. Поэтому перед разработчиками высоконагруженных систем встаёт задача обработки больших данных в реальном времени.

В этой статье вы узнаете:

  • что такое стриминговые фреймворки и для чего они нужны;

  • каковы основные особенности, архитектура и принцип работы Apache Flink;

  • в чём сходства и различия Apache Flink и Apache Spark;

  • каковы основные кейсы использования Apache Flink;

  • что нужно учитывать при проектировании приложений на основе Apache Flink.

Статья будет полезна архитекторам, системным аналитикам и проектировщикам систем, решающим задачи обработки больших данных в реальном времени.

Что такое стриминговые фреймворки и для чего они нужны

Потоковая обработка данных или Data Streaming ㅡ это подход, который позволяет обрабатывать большое количество данных в виде потока с минимальным отставанием от реального времени. 

Стриминговый фреймворк (stream processing framework) ㅡ это инструмент, позволяющий реализовать потоковую обработку данных. Стриминговый фреймворк умеет считывать один или несколько потоков данных из разных источников и производить их обработку. На выходе фреймворк может предоставлять обработанный поток данных для других приложений или складывать данные в базу данных или хранилище. 

Потоки данных бывают двух видов.

  1. Неограниченный поток (unbounded stream). Такой поток данных генерируется в реальном времени и не имеет определённого окончания. Пример неограниченного потока ㅡ поток данных из брокера сообщений о лайках и просмотрах пользователя.

  2. Ограниченный поток (bounded stream). Такой поток имеет чётко определённые начало и конец. Пример ограниченного потока ㅡ информация, получаемая из базы данных. Несмотря на то, что данные в базу могут добавляться, для стримингового фреймворка поток ограничен объёмом, полученным в рамках одного запроса.

Чаще всего при потоковой обработке основным источником является неограниченный поток. Данные из ограниченных потоков могут использоваться для дополнительного обогащения основного потока.

Рис. 1 ㅡ Ограниченные и неограниченные потоки данных (источник)
Рис. 1 ㅡ Ограниченные и неограниченные потоки данных (источник)

Подробнее об Apache Flink

Основные особенности фреймворка 

Apache Flink ㅡ это стриминговый фреймворк с открытым исходным кодом, предназначенный для потоковой обработки неограниченных и ограниченных потоков данных. 

Фреймворк обладает следующими основными особенностями.

  1. Обработка данных происходит построчно. Это играет важную роль в скорости обработки данных.

  2. Поддерживаемые языки программирования ㅡ Java, Scala, Python.

  3. Можно использовать расширенные оконные функции. Оконные функции позволяют разделить поток на сегменты ㅡ окна — и проводить операции над данными в рамках каждого окна.

  4. Можно реализовать подход exactly-once (строго однократная доставка, когда каждое входящее событие влияет на результат только один раз). Есть ограничение: источник и получатель данных тоже должны поддерживать подход exactly-once.

Эти особенности фреймворка позволяют реализовать обработку больших массивов данных в режиме реального времени.

Как работает Apache Flink

Верхнеуровнево процесс обработки данных с помощью Apache Flink можно изобразить так: 

Рис.2 ㅡ Обработка данных с помощью Apache Flink (источник)
Рис.2 ㅡ Обработка данных с помощью Apache Flink (источник)

Приложение на основе фреймворка считывает данные из различных источников (source). Источниками могут выступать неограниченные потоки в реальном времени из приложений, устройств и брокеров сообщений и ограниченные потоки из баз данных, файловых  хранилищ. 

Внутри приложение формирует направленный ациклический граф (DAG, directed acyclic graph). Каждый узел графа отвечает за выполнение какой-либо операции над данными (сортировка, фильтрация, вычисления и т. д.). Направленный граф может быть представлен в двух видах: логический и физический. 

Логический граф показывает какие операции будут проведены над данными. В логическом графе узлы называются операторами (operator). Физический граф ㅡ преобразованный для выполнения логический граф. В физическом графе каждый оператор может быть представлен несколькими задачами (Task). Задачи могут выполняться как параллельно, так и последовательно.  

Рис.3 ㅡ Направленный ациклический граф (DAG)
Рис.3 ㅡ Направленный ациклический граф (DAG)

После обработки приложение может отправить результаты получателям (Sink): в другие потоки для последующей обработки, в базы данных, хранилища и т. д.

State в Apache Fink

Вы могли слышать о существовании архитектурных концепций Stateful и Stateless

Stateful-архитектура

Stateless-архитектура

Смысл

Данные хранятся внутри сервиса между запросами и сеансами. 

Данные не хранятся внутри сервиса. 

Плюсы

быстрая обработка

возможность сохранять данные о состоянии между запросами для использования в следующих задачах

проще разрабатывать

лучшее масштабирование

меньшее потребление ресурсов

Минусы

дополнительная нагрузка на ресурсы системы

снижение производительности

больший объём данных для передачи между сервисами

сложность реализации сложной логики

Apache Flink позволяет реализовывать как Stateless, так и Stateful-приложения. Для обеспечения Stateful-вычислений в Apache Flink существует компонент Состояние (State).  Состояние ㅡ это слепок данных на конкретный момент времени. State хранится в оперативной памяти (in-memory), что позволяет максимально ускорить вычисления. 

Разберём работу State в Apache Flink на упрощённом примере. Предположим, что у нас есть задача посчитать сколько раз пользователи поставили лайк.

Рис.4 ㅡ State в Apache Flink
Рис.4 ㅡ State в Apache Flink

Предположим, что событие «Пользователь поставил лайк» пишется в брокер сообщений Apache Kafka. Приложение на основе Apache Flink вычитывает сообщения из брокера и разделяет поток данных по уникальным ключам (key). В примере ключом будет идентификатор пользователя. Для каждого пользователя приложение посчитает количество лайков на текущий момент. Когда пользователь поставит еще один лайк, он будет добавлен к уже имеющемуся количеству лайков. При этом предыдущее количество не нужно будет считывать из базы данных, оно будет храниться внутри приложения как State. Stateful-вычисления обеспечивают быструю обработку данных в подобных кейсах, когда важно знать предыдущие значения или состояния.

Важно, что состояние доступно только внутри задачи. В нашем примере общее число лайков будет существовать только в рамках задачи подсчёта лайков. Это ограничение обязательно нужно учитывать при проектировании приложений на основе Apache Flink. Если состояние нужно в других задачах, необходимо продумать как его передавать: это может быть новый поток данных или сохранение в базу данных. 

Рис. 5 ㅡ State в Apache Flink (источник)
Рис. 5 ㅡ State в Apache Flink (источник)

В больших высоконагруженных системах размер состояния может достигать нескольких терабайт. Для поддержки таких систем архитектура Apache Flink предполагает несколько вариантов хранения.

  1. В оперативной памяти. Подходит для приложений, в которых размер состояния ограничен несколькими гигабайтами. 

  2. В базе данных RocksDB. Подходит для высоконагруженных приложений. За размещение состояния в базе данных отвечает специально выделенный под это State Backend.

Job Manager и Task Manager

Apache Flink разворачивается с помощью двух компонентов: Job Manager и Task Manager. 

Job Manager ㅡ это оркестратор, центральный компонент архитектуры Apache Flink, отвечающий за координацию распределённого исполнения приложения. Job manager выполняет множество задач:

  • планирует выполнение задач;

  • реагирует на выполнение задач или ошибки в процессе выполнения;

  • координирует checkpoints ㅡ механизм периодического резервного сохранения состояния на случай сбоя;

  • координирует восстановление после сбоев.

Task Manager ㅡ это основной рабочий процесс в архитектуре Apache Flink, он отвечает за выполнение конкретной задачи.

Рис. 6 ㅡ Job Manager и Task Manager в Apache Flink
Рис. 6 ㅡ Job Manager и Task Manager в Apache Flink

При развёртывании Apache Flink-приложения нужно учитывать, что Job Manager относительно легковесен и под него нужно выделить меньшее количество ресурсов, чем под Task Manager.

Сравнение Apache Spark и Apache Flink

Фреймворки Apache Spark и Apache Flink часто сравнивают и ставят в один ряд. Они действительно похожи:

  • могут обрабатывать большие потоки данных;

  • позволяют использовать оконные функции и агрегировать данные;

  • позволяют реализовать сложную логику: соединение потоков, фильтрация, группировка и т.д.;

  • работают с языками программирования Java, Scala, Python;

  • поддерживают гарантию доставки at-least-once;

  • могут подключаться к брокерам сообщений, базам данных, хранилищам как в качестве источников данных, так и в качестве получателей.

Фреймворки имеют и существенные различия:

  • главное различие ㅡ способ обработки информации. Flink обрабатывает данные построчно: это позволяет обрабатывать данные в реальном времени с минимальной задержкой. Spark обрабатывает данные микро-батчами (batch) ㅡ комбинациями нескольких строк. Это позволяет повысить производительность расчётов над данными внутри батча.

  • разная архитектура и механизмы развёртывания. Например, Spark не имеет Task Manager и Job Manager, вместо них используются другие компоненты. 

  • Spark имеет высокий порог входа по сравнению с Flink, считается более сложным в освоении.

Выбор фреймворка зависит от потребности и задачи. 

Spark чаще используется на стыке бэкенда и хранилища, например DWH. Это могут быть задачи применения моделей машинного обучения на потоке данных или накопления данных в хранилище для дальнейшей аналитики. 

Flink чаще всего используется на уровне бэкенда. Рассмотрим подробнее основные кейсы применения Apache Flink.

Основные кейсы применения Apache Flink

Выделяют три основных кейса, в которых Apache Flink может быть успешно применён.

  1. Социальные сети и системы рекомендаций. Допустим, приложение генерирует поток данных поведения пользователей (клики, лайки, просмотры, комментарии и т.д.). С помощью Apache Flink можно реализовать механизм подсчета действий пользователей в реальном времени. Дальше данные могут передаваться в:

    1. базы данных ㅡ источник для отображения на страницах приложения;

    2. хранилища, например, DWH ㅡ источники для построения рекомендаций релевантных продуктов, контента или рекламы.

  2. Выявление мошенничества. Apache Flink позволяет реализовать анализ поведения пользователей и немедленную реакцию в случаях странного, отличающегося от заданного шаблона поведения.  

  3. Обнаружение аномалий.  Фреймворк можно использовать для мониторинга состояния системы (в том числе ИТ-инфраструктуры) и моментального оповещения об отклонениях метрик от нормальных значений. 

Разберём на примере, как может работать приложение для обнаружения мошенничества на основе Apache Flink.

Рис. 7 - Обнаружение мошенничества с помощью Apache Flink (источник)
Рис. 7 - Обнаружение мошенничества с помощью Apache Flink (источник)

На входе приложения два потока данных.

  1. Поток действий пользователей (User Actions). Это могут быть вход и выход из системы, пополнение корзины, оплата и т.д.

  2. Поток заданных паттернов поведения (Patterns). Например, в паттерн заложено, что добавление товара в корзину и немедленный выход из системы может говорить о мошенничестве.

Приложение соединяет два потока данных (например, с помощью оконных функций), и ожидает, пока пользователь выполнит какие-то действия. Реализовать ожидание ряда действий пользователя позволяет State, о котором мы говорили ранее. 

Если поведение совпадает с паттерном, приложение отправит уведомление о том, что пользователь ведёт себя странно и нужно обратить на него внимание. 

Что нужно учитывать при проектировании приложения на основе Apache Flink? 

  1. Логика обработки потока. Какие операции необходимо совершить над данными: фильтрация, группировка, бизнес-логика и т.д.

  2. Нужны ли ключи в операторах? Если да, то сколько и какие? 

  3. Нужен ли State? Если да, то какого он будет размера? Можно ли установить время жизни (TTL, Time To Live) для State?

  4. Надо ли транслировать State в другие операторы? Если да, то каким образом это делать? 

Резюме

  1. Стриминговые фреймворки позволяют реализовать потоковую обработку больших данных в реальном времени. 

  2. Apache Flink может обрабатывать как ограниченные, так и неограниченные потоки данных, поступающие из брокеров сообщений, баз данных и хранилищ. Логика обработки в Apache Flink реализуется через направленный ациклический граф. Apache Flink позволяет реализовать stateful-вычисления.

  3. При проектировании приложения на основе Apache Flink основное внимание нужно уделить логике построения направленного ациклического графа.

Дополнительные источники

  1. O'Reilly: Уэске Ф., Калари В. Потоковая обработка данных с Apache Flink.

  2. Официальная документация к Apache Flink.

Автор статьи — Дарья Колесова

Руководитель группы инженерии качества данных.

Опыт в ролях: Big Data R&D разработчик, BI Engineer, Data-аналитик, технический лид.

Более 5 лет в Big Data разработке.

Более 3 лет в роли тренера.

Комментарии (1)


  1. Marsezi
    25.09.2024 11:55

    Вот на примере лайков. Flink как вы пишете работает без batch в реальном времени. Считаем лайки и как они в базу пишутся ? Также на каждый лайк происходит update в базу данных для пользователя?

    Это же создаст туже нагрузку что я просто буду писать напрямую в базу update like++