Справочник ключевых терминов курса Apache Flink.
Базовая абстракция Flink для распределённого потенциально-бесконечного потока событий. DataStream<T> описывает поток элементов типа T, который преобразуется операторами (map, filter, keyBy, window, process) в новый DataStream. Это logical handle — реальные элементы обрабатываются параллельно subtasks во время выполнения.
DataStream<Event> events = env.fromSource(kafkaSource, WatermarkStrategy.forBoundedOutOfOrderness(Duration.ofSeconds(5)), "kafka");Парадигма обработки данных, при которой записи обрабатываются по одной (или микро-батчем) сразу при поступлении, а не накапливаются и обрабатываются батчем. В отличие от batch (Spark, MapReduce), state и time являются first-class сущностями, а pipeline работает непрерывно с low-latency результатом.
Flink, Kafka Streams, Spark Structured Streaming — все реализации stream processing.Directed Acyclic Graph — представление job как графа операторов без циклов. Каждая нода — это transformation (source, map, keyBy, sink), каждая edge — поток данных между ними. Flink строит logical DAG из API-вызовов, затем оптимизирует его в JobGraph для исполнения.
Source -> Map -> KeyBy -> Window -> Sink — классический DAG для агрегации.Logical-уровень представление job, который клиент отправляет в JobManager. Получается из StreamGraph после оптимизаций: chaining операторов в одну задачу для уменьшения сериализации/network overhead. JobGraph содержит JobVertices и IntermediateDataSets.
Physical-уровень граф, который JobManager разворачивает из JobGraph для исполнения. Каждая JobVertex превращается в ExecutionVertices по числу parallelism — это реальные subtasks, которые JobManager планирует на TaskManager slots.
Параллельный экземпляр оператора. Если оператор имеет parallelism=8, у него 8 subtasks, каждый обрабатывает свою долю данных. Subtasks выполняются в task slots на TaskManager-ах и обмениваются данными через сетевые буферы.
Число параллельных subtasks для оператора или job. Задаётся глобально (env.setParallelism(N)), на уровне оператора (.setParallelism(N)) или через config (parallelism.default). С Flink 1.13+ доступен adaptive scheduler, который может менять parallelism без рестарта.
env.setParallelism(16); stream.keyBy(...).process(new MyFn()).setParallelism(8);DataStream, разбитый на логические партиции по ключу через keyBy(). Все элементы с одинаковым ключом гарантированно попадают в один и тот же subtask, что позволяет использовать keyed state и keyed timers. Hash-partitioning по результату KeySelector.
DataStream<Order> orders = ...; KeyedStream<Order, String> byUser = orders.keyBy(Order::getUserId);Логическая группировка событий по времени или количеству для агрегации. Flink определяет окна через WindowAssigner (Tumbling/Sliding/Session/Global), Trigger (когда вычислять) и Evictor (опционально удалять элементы). Windows работают только на KeyedStream (или AllWindow на DataStream — но без параллелизма).
Время, когда событие произошло в источнике (extracted из самого payload). В отличие от processing time, не зависит от задержек в pipeline, что делает результаты детерминированными даже при re-processing. Требует watermarks для определения completeness.
Время на wall-clock-часах машины, обрабатывающей событие. Самый быстрый и простой режим, но недетерминированный: при reprocessing получаются другие результаты. Подходит когда latency важнее точности и нет out-of-order.
Специальный mark в потоке, сигнализирующий что все события с timestamp <= W уже пришли (с допустимой погрешностью). Watermark двигает event time forward, триггерит закрытие event-time окон и срабатывание event-time timers. Генерируется WatermarkStrategy в source.
API для генерации watermarks: WatermarkGenerator (per-event onEvent + periodic onPeriodicEmit) и TimestampAssigner (extract timestamp from event). Стандартные: forBoundedOutOfOrderness, forMonotonousTimestamps, noWatermarks.
WatermarkStrategy.<Event>forBoundedOutOfOrderness(Duration.ofSeconds(10)).withTimestampAssigner((e, t) -> e.eventTime()).withIdleness(Duration.ofMinutes(1));Окна фиксированной длины без перекрытия. TumblingEventTimeWindows.of(Time.minutes(5)) — каждые 5 минут открывается новое окно и закрывается, когда watermark переходит его конец. Самый простой window assigner.
Окна фиксированной длины с фиксированным шагом, перекрывающиеся. SlidingEventTimeWindows.of(size, slide): окно size=10min, slide=1min — каждую минуту открывается новое 10-минутное окно. Один элемент попадает в size/slide окон.
Окно динамической длины, разделённое gap-периодами неактивности. EventTimeSessionWindows.withGap(Time.minutes(30)): если между событиями ключа разрыв >30min — это разные сессии. Окно закрывается, когда watermark переходит timestamp последнего события + gap.
Период после закрытия окна watermark-ом, в течение которого позднеприбывшие события всё ещё триггерят повторное вычисление окна. Window.allowedLateness(Time.minutes(5)). По истечении state окна удаляется.
Механизм синхронизации watermark между source partitions/splits — медленные splits искусственно ускоряются (или быстрые тормозятся), чтобы максимальное расхождение event-time не превышало threshold. Уменьшает накопление state в окнах при skew. Доступно с Flink 1.15.
Параметр WatermarkStrategy.withIdleness(timeout) — если split/partition не присылает событий в течение timeout, он помечается idle и игнорируется при вычислении minimum watermark. Решает проблему остановки watermark из-за пустой Kafka-партиции.
State, привязанный к ключу keyBy. Каждый ключ имеет свой независимый state, доступный только когда обрабатывается элемент с этим ключом. Типы: ValueState, ListState, MapState, ReducingState, AggregatingState. Хранится в state backend, чекпойнтится автоматически.
ValueState<Long> count = getRuntimeContext().getState(new ValueStateDescriptor<>("count", Long.class));State, привязанный к параллельной инстанции (subtask) оператора, не к ключу. Используется в Source/Sink connector-ах для хранения offset/position. Типы: ListState (равномерно перераспределяется при rescale), UnionListState (каждый subtask получает union), BroadcastState (read-only копия везде).
Специальный тип Operator State: один и тот же snapshot реплицируется на все параллельные subtasks. Используется для broadcast pattern: правила/rules-stream рассылается всем subtasks, а основной поток обогащается через connect+process. Read-only в BroadcastProcessFunction.processElement.
Самый простой keyed state — хранит одно значение типа T на ключ. update(T), value() — get, clear(). Если ничего не записано, value() вернёт null или default из descriptor.
ValueState<Long> sum = getRuntimeContext().getState(new ValueStateDescriptor<>("sum", Long.class)); sum.update(sum.value() + 1);Keyed state, хранящий список значений на ключ. add(T), get() возвращает Iterable, update(List), clear(). Полезен для накопления событий до триггера (например, в session-агрегации).
Keyed state как map: put(K,V), get(K), remove(K), entries(), iterator(). Для каждого ключа keyBy — свой Map. Эффективнее ValueState<Map> на RocksDB, так как операции происходят без полной сериализации всего map.
Механизм автоматической экспирации state-записей по времени. Настраивается через StateTtlConfig: ttl, UpdateType (OnCreateAndWrite / OnReadAndWrite), StateVisibility (NeverReturnExpired / ReturnExpiredIfNotCleanedUp). С Flink 1.13+ работает на user timers, что делает cleanup детерминированным.
StateTtlConfig.newBuilder(Duration.ofDays(7)).setUpdateType(UpdateType.OnCreateAndWrite).cleanupInRocksdbCompactFilter(1000).build();Компонент, отвечающий за хранение и сериализацию state. С Flink 1.13+ разделение: StateBackend (working state — HashMap или RocksDB) и CheckpointStorage (where to store checkpoint — JobManagerCheckpointStorage или FileSystemCheckpointStorage). Выбор влияет на throughput, latency, scalability.
State backend, хранящий state в JVM heap как обычные Java объекты. Самый быстрый по latency, но ограничен размером heap и подвержен GC pauses. Подходит для маленького state (<100MB на TaskManager) и low-latency workload.
State backend на основе embedded LSM-tree RocksDB. State хранится off-heap на локальном диске, что позволяет масштабировать до сотен GB на TaskManager. Поддерживает incremental checkpoints — снимает только изменения SST-файлов. Trade-off: serialization overhead на каждый state-доступ.
Автоматический snapshot всего state job-а, делается периодически (env.enableCheckpointing(interval)) для fault tolerance. Координируется JobManager через barriers, прокинутые через DAG. При failure job рестартится с последнего успешного checkpoint. Управляется системой, не пользователем.
Manually triggered consistent snapshot job-а для admin-операций: upgrade, rescale, migration, A/B сравнение. В отличие от checkpoint, savepoint не удаляется автоматически, имеет более стабильный формат и предназначен для портативности между версиями Flink.
Оптимизация для RocksDB backend: чекпойнтятся только новые/изменённые SST-файлы с прошлого успешного checkpoint. Кардинально снижает размер записываемых данных при big state, ускоряет checkpoint duration. Полные checkpoint восстанавливаются из набора инкрементов.
Дополнительный output stream, обычно для late events или для разделения событий по типам без полного дублирования pipeline. Создаётся через OutputTag в ProcessFunction.Context.output(tag, value), извлекается через stream.getSideOutput(tag).
Низкоуровневый Java/Scala API Flink для работы с потоками: explicit map/filter/keyBy/process, прямое управление state и timers. Даёт максимум контроля, но требует больше кода. Альтернатива — Table API/SQL.
Declarative relational API поверх DataStream/DataSet: операции tableEnv.from(...).select(...).groupBy(...).window(...). Конвертируется через Calcite в physical plan. Семантически эквивалентна Flink SQL, но через fluent Java/Python API.
Низкоуровневый оператор DataStream API с прямым доступом к state, timers и Context (timestamp, watermark, side outputs). KeyedProcessFunction даёт ещё и keyed state и keyed timers. Используется когда built-in операторы не покрывают логику.
Оператор для асинхронного обогащения потока внешним lookup-ом (HTTP, DB, gRPC). Не блокирует subtask на каждом запросе — несколько запросов в-полёте параллельно. Конфигурируется через AsyncDataStream.unorderedWait(..., capacity, timeout).
Pattern и API в DataStream для асинхронного обогащения с ограничением concurrency. Ключевые параметры: capacity (in-flight requests на subtask), timeout (на запрос), ordered vs unordered output. Без него каждый sync lookup тормозит весь subtask.
Новый Source API (FLIP-27), стандарт с Flink 1.12+. Разделяет SplitEnumerator (координирует распределение работы) и SourceReader (читает данные в subtask). Поддерживает unified batch/streaming, watermark generation, checkpointing offset-ов.
Новый Sink API (FLIP-191/171), стандарт с Flink 1.15+. Разделяет SinkWriter (запись), Committer (двухфазный commit для exactly-once), GlobalCommitter (опционально). Базис для TwoPhaseCommittingSink — стандартный exactly-once sink.
Реализация Source для конкретного external system (Kafka, Kinesis, JDBC, files). Отвечает за discovery splits, чтение данных, генерацию watermarks, чекпойнтинг offset. Распространяется как отдельный maven artifact.
Реализация Sink для конкретного external system (Kafka, Iceberg, Paimon, JDBC, OpenSearch). С Flink 2.x — на базе Sink V2. Может поддерживать AT_LEAST_ONCE, EXACTLY_ONCE через 2PC, или NONE.
ANSI SQL диалект Flink для streaming queries. Парсится Calcite, оптимизируется в логический план, потом в Table API operators, потом в DataStream. Поддерживает streaming семантику: continuous queries возвращают changelog stream.
Концепция Table API/SQL: таблица, содержимое которой меняется во времени. Continuous query на dynamic table тоже возвращает dynamic table — её изменения публикуются как changelog stream (insert/update/delete events).
Stream of changes к dynamic table: +I (insert), -U (delete старого), +U (insert нового), -D (delete). Materialized form dynamic table. Используется для CDC: source даёт changelog, sink его применяет.
Способы кодировать изменения в changelog stream. Retract mode: каждое update — это pair (-U старого, +U нового). Upsert mode: каждое событие — full row с primary key, sink делает upsert. Connector декларирует поддерживаемые режимы.
Apache Calcite — SQL parser и query optimizer, на основе которого построена Flink Table/SQL infrastructure. Парсит SQL в AST, применяет logical/physical rules optimization, генерирует Flink-specific plan, который дальше превращается в DataStream operators.
SQL JOIN, у которого правая таблица versioned по времени (versioned table). Каждая строка левой таблицы джойнится со строкой правой, активной на момент event-time левой. Типичный кейс: enrichment курсами валют, актуальными на момент транзакции.
SQL/DataStream JOIN на event-time с временным интервалом: a.ts BETWEEN b.ts - INTERVAL '5' MINUTE AND b.ts + INTERVAL '5' MINUTE. State держится не вечно, ограничен интервалом, что делает join scalable.
SQL-конструкция для распознавания паттернов в потоке (CEP — complex event processing). Описывает sequence событий через regex-like pattern, измерения и define-условия. Альтернатива legacy DataStream CEP library, doc-friendly.
SELECT * FROM orders MATCH_RECOGNIZE(PARTITION BY userId ORDER BY ts MEASURES A.ts AS startTs PATTERN (A B+ C) DEFINE B AS B.amount > A.amount);Фича Flink SQL 1.20+: декларативные continuously refreshing tables, описанные SELECT-запросом плюс freshness target. Flink сам решает, как поддерживать материализацию (continuously или scheduled refresh). Упрощает построение lakehouse data products.
Master-процесс Flink-кластера. Координирует execution: принимает JobGraph, строит ExecutionGraph, планирует subtasks на TaskManager slots, триггерит checkpoints, реагирует на failures (restart strategy). В HA mode несколько JobManager через ZooKeeper/K8s leader election.
Worker-процесс Flink-кластера. Содержит фиксированное число task slots, в которых выполняются subtasks. Отвечает за обмен данными между subtasks, локальное хранение state (RocksDB SST), кэширование. В K8s — Pod.
Unit ресурсов TaskManager-а. Каждый slot — изолированный набор managed memory, в котором могут выполняться subtasks одного pipeline (slot sharing). taskmanager.numberOfTaskSlots определяет число slots на TaskManager. Общее число slots в кластере = TM * slotsPerTM = max parallelism.
По умолчанию subtasks разных операторов одного pipeline могут делить один slot. Это оптимизирует throughput (меньше cross-network), позволяет parallelism job равняться max(parallelism оператора), а не сумме.
Режим deployment Flink job, при котором main() выполняется в JobManager-процессе, и каждый job получает свой dedicated cluster. Стандарт для production на K8s через Flink K8s Operator. Альтернатива Session Mode.
Режим deployment, при котором long-running cluster принимает несколько job-ов через REST/CLI. Хорош для ad-hoc/dev/notebook сценариев и Flink SQL. Не рекомендуется для production: один rogue job может уронить всё.
Официальный Kubernetes Operator от Apache Flink для управления Flink job-ами как K8s CRD. Реализует lifecycle: deploy, rollback, suspend, upgrade с автоматическим savepoint. Версия 1.14 (май 2026) — рекомендуемая, поддерживает Flink 1.20 LTS и 2.x.
Custom Resource Definition Flink K8s Operator-а, описывающий желаемое состояние Flink job-а: image, replicas, taskmanager/jobmanager resources, job.upgradeMode, savepoint config. Operator-reconciler приводит реальность к описанному.
apiVersion: flink.apache.org/v1beta1
kind: FlinkDeployment
metadata:
name: my-job
spec:
image: my-job:v1.2.3
flinkVersion: v2_2
job:
upgradeMode: savepointHigh Availability для JobManager — несколько JobManager одновременно, один leader через distributed coordination (ZooKeeper или Kubernetes-native через ConfigMap + leases). При падении leader другой подхватывает с метаданных в HA storage (PVC/S3).
Стратегия upgrade FlinkDeployment в Operator: SAVEPOINT (trigger savepoint, потом restart с него — гарантирует exactly-once), LAST_STATE (restart с последнего checkpoint — быстрее, но требует HA), STATELESS (полный пересоздать, теряет state).
Deployment-pattern для миграции Flink job без downtime: новый job (green) стартует со стартового savepoint в parallel со старым (blue), оба работают, traffic переключается на sink-уровне, blue выключается. Реализуется через два FlinkDeployment.
Streaming lakehouse format (бывший Flink Table Store, top-level Apache project с 2024). Spec-первый формат поверх Parquet/ORC с LSM-tree организацией для high-throughput updates. Нативно интегрирован с Flink: streaming sink через TwoPhaseCommittingSink, time-travel queries, schema evolution.
Open table format (Apache, top-level), снапшот-based ACID layer поверх Parquet/Avro/ORC в object storage. Flink IcebergSink с EXACTLY_ONCE через 2PC. Standard de-facto для batch+streaming unified lakehouse. Сравнение: Iceberg ориентирован на batch-heavy с low-frequency commits.
Open table format Apache Hudi, альтернатива Iceberg, оптимизирован для upserts через MoR (Merge-on-Read) и CoW (Copy-on-Write) tables. Flink-Hudi integration существует, но в комьюнити менее активна, чем Iceberg/Paimon в 2026.
Новый streaming storage от создателей Flink (Apache Incubator, 2024). Pub-sub слой со встроенным columnar storage и changelog semantics, оптимизирован под Flink. Перспективная альтернатива Kafka+Paimon для streaming lakehouse в 2026.
Часть памяти TaskManager-а под управлением Flink runtime (taskmanager.memory.managed.size/fraction). Используется RocksDB block cache, sort/hash buffers (batch), Python runners. Управление вытеснением — Flink, не JVM GC. Под-tuning влияет на throughput больше всего на RocksDB workload.
Scheduler, который может менять parallelism job без полного restart (с 1.13, default для streaming с 1.15 в Application Mode). Реагирует на изменение доступных slots, делает rescale через savepoint+rescale внутренне. Совмещается с reactive mode для autoscaling.
Состояние, когда downstream оператор не успевает обрабатывать данные, и upstream вынужден замедляться. Flink реализует backpressure через credit-based flow control в сетевом стеке. Видно в Web UI как 'BUSY/BACKPRESSURED' subtasks. Источник: slow sink, skewed key, GC, async I/O capacity.
Алгоритм distributed snapshot (1985), на базе которого реализован Flink checkpoint. Coordinator-процесс инжектит markers (barriers) в каналы, каждый процесс снимает свой state при получении marker от каждого канала, что даёт consistent global snapshot без остановки computation.
Специальный mark в потоке данных, инжектится JobManager-ом в source для каждого checkpoint. Когда оператор получает barriers от всех input channels, он snapshot-ит свой state и forward barrier дальше. Aligned barriers требуют ждать barriers со всех каналов; unaligned — нет.
Режим checkpoint, при котором оператор не ждёт barriers со всех input каналов, а сразу snapshot-ит свой state + in-flight buffers (данные, прошедшие barrier и стоящие в очереди). Решает проблему backpressure-blocked checkpoints. Дороже по storage. С 1.13+ production-ready.
Distributed commit protocol для exactly-once sink. Phase 1 (precommit): на каждый checkpoint sink записывает данные в transactional/staging state, готов к commit. Phase 2 (commit): после notifyCheckpointComplete все participants коммитят. При failure — rollback или idempotent replay.
Стандартный интерфейс Sink V2 для exactly-once sink. Реализуется через SinkWriter (precommit — пишет в staging) + Committer (commit на notifyCheckpointComplete). Базис для KafkaSink, IcebergSink, JdbcSink (в режиме EXACTLY_ONCE).
Enum в Sink V2, описывающий уровень гарантий: NONE (best effort, может терять/дублировать), AT_LEAST_ONCE (может дублировать, но не терять), EXACTLY_ONCE (через 2PC, не теряет и не дублирует). Выбирается в builder sink-а.
KafkaSink.builder().setDeliveryGuarantee(DeliveryGuarantee.EXACTLY_ONCE).setTransactionalIdPrefix("app-").build();Kafka producer в transactional mode (transactional.id, initTransactions, beginTransaction, commitTransaction). Flink KafkaSink в EXACTLY_ONCE использует pool transactional producers: на precommit делает sendOffsetsToTransaction + flush, на commit — commitTransaction. Требует isolation.level=read_committed на consumer-ах.
Stable identifier оператора в job graph, задаётся через .uid("name"). Используется для матчинга state в savepoint при restore. Если UID изменился — state считается чужим и не восстанавливается. Обязателен для stateful операторов в production.
Подпроект Flink (с 2021, стал top-level в 2024) для Change Data Capture из реляционных БД. Объединяет Debezium engine + Flink runtime: snapshot phase + streaming binlog/WAL phase, schema evolution, exactly-once. С Flink CDC 3.x — YAML pipeline без Java-кода.
Архитектура Flink CDC: библиотеки Debezium запускаются inside Flink source operator, без отдельного Kafka Connect cluster. Это уменьшает infrastructure footprint и позволяет single-source-of-truth pipeline. Альтернатива — Debezium через Kafka Connect.
Initial bootstrap фаза Flink CDC: читает таблицу через SELECT с chunk-based parallel snapshot (Incremental Snapshot Framework). Не требует stop-the-world lock. После snapshot переходит в streaming phase с WAL/binlog позиции, зафиксированной до snapshot.
Основная фаза Flink CDC после snapshot: реад из transaction log БД (MySQL binlog, Postgres WAL, MongoDB oplog) в реальном времени. Каждое изменение конвертируется в changelog event (+I/-U/+U/-D). Offset binlog/LSN чекпойнтится автоматически.
Способность pipeline переживать изменения схемы source/sink (add/drop column, rename, type change). Flink CDC 3.x пропускает DDL events из source как schema change events, sink connector применяет их к target таблице (если поддерживает — например Paimon, Iceberg).