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

В этой статье вы узнаете:
  • что такое стриминговые фреймворки и для чего они нужны;
  • каковы основные особенности, архитектура и принцип работы Apache Flink;
  • в чём сходства и различия Apache Flink и Apache Spark;
  • каковы основные кейсы использования Apache Flink;
  • что нужно учитывать при проектировании приложений на основе Apache Flink.
Статья будет полезна архитекторам, системным аналитикам и проектировщикам систем, решающим задачи обработки больших данных в реальном времени.
Что такое стриминговые фреймворки
и для чего они нужны
Потоковая обработка данных или Data Streaming ㅡ это подход, который позволяет обрабатывать большое количество данных в виде потока с минимальным отставанием от реального времени.

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

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

Чаще всего при потоковой обработке основным источником является неограниченный поток. Данные из ограниченных потоков могут использоваться для дополнительного обогащения основного потока.
Рис. 1 ㅡ Ограниченные и неограниченные потоки данных
Подробнее об Apache Flink
Основные особенности фреймворка
Apache Flink ㅡ это стриминговый фреймворк с открытым исходным кодом, предназначенный для потоковой обработки неограниченных и ограниченных потоков данных.

Фреймворк обладает следующими основными особенностями.
  1. Обработка данных происходит построчно. Это играет важную роль в скорости обработки данных.
  2. Поддерживаемые языки программирования ㅡ Java, Scala, Python.
  3. Можно использовать расширенные оконные функции. Оконные функции позволяют разделить поток на сегменты ㅡ окна — и проводить операции над данными в рамках каждого окна.
  4. Можно реализовать подход exactly-once (строго однократная доставка, когда каждое входящее событие влияет на результат только один раз). Есть ограничение: источник и получатель данных тоже должны поддерживать подход exactly-once.

Эти особенности фреймворка позволяют реализовать обработку больших массивов данных в режиме реального времени.
Как работает Apache Flink
Верхнеуровнево процесс обработки данных с помощью Apache Flink можно изобразить так:
Рис.2 ㅡ Обработка данных с помощью Apache Flink
Приложение на основе фреймворка считывает данные из различных источников (source). Источниками могут выступать неограниченные потоки в реальном времени из приложений, устройств и брокеров сообщений и ограниченные потоки из баз данных, файловых хранилищ.

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

Логический граф показывает какие операции будут проведены над данными. В логическом графе узлы называются операторами (operator). Физический граф ㅡ преобразованный для выполнения логический граф. В физическом графе каждый оператор может быть представлен несколькими задачами (Task). Задачи могут выполняться как параллельно, так и последовательно.
Рис.3 ㅡ Направленный ациклический граф (DAG)
После обработки приложение может отправить результаты получателям (Sink): в другие потоки для последующей обработки, в базы данных, хранилища и т.д.
State в Apache Fink
Вы могли слышать о существовании архитектурных концепций Stateful и Stateless.
Apache Flink позволяет реализовывать как Stateless, так и Stateful-приложения. Для обеспечения Stateful-вычислений в Apache Flink существует компонент Состояние (State). Состояние ㅡ это слепок данных на конкретный момент времени. State хранится в оперативной памяти (in-memory), что позволяет максимально ускорить вычисления.

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

Важно, что состояние доступно только внутри задачи. В нашем примере общее число лайков будет существовать только в рамках задачи подсчёта лайков. Это ограничение обязательно нужно учитывать при проектировании приложений на основе 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
При развёртывании 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 можно реализовать механизм подсчета действий пользователей в реальном времени. Дальше данные могут передаваться в:
  • базы данных ㅡ источник для отображения на страницах приложения;
  • хранилища, например, DWH ㅡ источники для построения рекомендаций релевантных продуктов, контента или рекламы.
2. Выявление мошенничества. Apache Flink позволяет реализовать анализ поведения пользователей и немедленную реакцию в случаях странного, отличающегося от заданного шаблона поведения.
3. Обнаружение аномалий. Фреймворк можно использовать для мониторинга состояния системы (в том числе ИТ-инфраструктуры) и моментального оповещения об отклонениях метрик от нормальных значений.

Разберём на примере, как может работать приложение для обнаружения мошенничества на основе 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 основное внимание нужно уделить логике построения направленного ациклического графа.
Дополнительные источники
Об авторе
Дарья Колесова
Руководитель группы инженерии качества данных в Самокате
  • Опыт в ролях: Big Data R&D разработчик, BI Engineer, Data-аналитик, технический лид;
  • Более 5 лет в Big Data разработке;
  • Более 3 лет в роли тренера.