Airflow на собеседовании Data Engineer

Зачем DE спрашивают про Airflow

Airflow — стандартный инструмент оркестрации batch ETL-пайплайнов. Используется в Yandex, Tinkoff, Ozon, Avito, и почти всех крупных компаниях. На собесе Data Engineer Airflow — обязательный блок: либо отдельным разделом, либо в системном дизайне.

Уровень вопросов: junior — знает синтаксис DAG, операторы; middle — пишет idempotent DAG-и, обрабатывает retry; senior — проектирует архитектуру оркестрации для всей компании, понимает scheduler internals.

Базовая архитектура

Webserver — UI и REST API.

Scheduler — оркестратор: парсит DAG-и, шедулит таски, разделяет работу между workers.

Worker — выполняет таски. Executor: Sequential / Local / Celery / Kubernetes.

Metadata DB — PostgreSQL (default) или MySQL. Хранит DAG runs, task instances, XCom, variables.

DAG bag — каталог DAG-файлов. Scheduler парсит регулярно.

DAG и операторы

DAG — Directed Acyclic Graph. Описание pipeline:

from airflow import DAG
from datetime import datetime

with DAG(
    'my_dag',
    start_date=datetime(2026, 5, 1),
    schedule_interval='@daily',
    catchup=False,
    max_active_runs=1,
) as dag:
    task1 >> task2 >> task3

Операторы — типы тасков:

  • PythonOperator — выполняет Python-функцию
  • BashOperator — bash-команда
  • PostgresOperator / MySqlOperator — SQL запросы
  • S3ToRedshiftOperator — типовые перемещения
  • TaskFlow API (@task decorator) — более pythonic-стиль

Идемпотентность

Главное правило DE — DAG должен быть идемпотентным. Повторный запуск даёт тот же результат.

Почему важно: задачи падают, retries и backfill — обычное дело. Не идемпотентный DAG = дубликаты или потери при retry.

Как достичь:

  1. Параметризовать по execution_date. Не использовать datetime.now() в DAG.
  2. MERGE / UPSERT вместо INSERT. UPSERT по primary key.
  3. Delete partition перед записью. DELETE WHERE date = {{ ds }}; INSERT INTO ... WHERE date = {{ ds }}
  4. Transaction guarantees. Атомарная запись или roll-back.

Sensors

Sensors ждут события: появление файла, новой партиции, статуса внешней системы.

from airflow.sensors.s3_key_sensor import S3KeySensor

wait_for_file = S3KeySensor(
    task_id='wait_for_data',
    bucket_key='s3://bucket/data/{{ ds }}/*.parquet',
    poke_interval=60,
    timeout=3600,
)

Проблема: sensors занимают worker-slot всё время ожидания. Решение — reschedule mode (mode='reschedule'). Sensor отпускает слот между проверками.

Smart sensor / Deferrable operators — Airflow 2+ — sensors работают через async без блокировки слотов.

XCom

XCom — передача данных между тасками. Хранится в metadata DB.

def push_data(**context):
    context['ti'].xcom_push(key='result', value=42)

def pull_data(**context):
    value = context['ti'].xcom_pull(task_ids='push_task', key='result')

Ограничения:

  • Размер: только маленькие payload-ы (метаданные, IDs). XCom хранится в metadata DB
  • Performance: каждый XCom — запись в metadata DB

Для больших данных: передавай через external storage (S3 path), а через XCom — только путь.

Backfill

Backfill — запуск DAG-а на исторический период. Например, новый pipeline для последних 90 дней:

airflow dags backfill my_dag --start-date 2026-02-01 --end-date 2026-05-01

Требования к backfill:

  1. DAG должен быть идемпотентным
  2. catchup=False или catchup=True — выбор архитектора
  3. depends_on_past=True если порядок важен

Scheduler internals

DAG parsing — scheduler регулярно парсит DAG-файлы. Если 1000 DAG-ов с медленными импортами — scheduler тормозит.

Trigger rules:

  • all_success (default) — все upstream успешно
  • one_success — хотя бы один
  • all_failed — все провалились
  • one_failed — хотя бы один
  • all_done — все завершены (любой статус)

Pool — ограничение параллелизма по группе задач. Например, «к одной БД не более 5 задач».

Типичные вопросы

«Что значит идемпотентность DAG?»

Многократный запуск даёт тот же результат. Достигается через параметризацию по execution_date, MERGE вместо INSERT, удаление целевой партиции перед записью.

«Чем catchup=True отличается от catchup=False

catchup=True — Airflow запустит DAG за все прошедшие интервалы с start_date. catchup=False — только начиная с текущего момента. По умолчанию True, в production обычно False (если не нужен исторический запуск).

«DAG не запускается. Что проверить?»

(1) Включён ли (paused/unpaused), (2) start_date — в прошлом ли, (3) schedule_interval не пустой, (4) max_active_runs не ограничивает, (5) scheduler здоров (логи), (6) dependencies upstream success.

«Как обработать late-arriving данные?»

Несколько вариантов: (1) повторный запуск нужных партиций (backfill), (2) DAG ждёт данные через sensor с timeout, (3) отдельный «reprocessing» DAG для late events.

«XCom для больших данных?»

Не используй XCom для больших объёмов. Передавай через external storage — S3, HDFS, ClickHouse table. Через XCom — только path или ID.

Частые ошибки

  • datetime.now() в DAG. Делает DAG неидемпотентным. Используй {{ ds }} или execution_date
  • Insert вместо MERGE. При retry получаешь дубликаты
  • Большие XCom. Забивает metadata DB
  • Sensor без reschedule mode. Занимает worker-slot часами
  • Тяжёлые импорты в DAG-файле. Тормозит scheduler

FAQ

Какие альтернативы Airflow?

Dagster — современная альтернатива, фокус на data assets. Prefect — лёгкий, Python-native. Luigi — старый, ещё используется. На собесе обычно Airflow — стандарт de facto.

Airflow 2 vs 3?

Airflow 2 — мейнстрим в 2024-2026. Airflow 3 в активной разработке. На собесе обычно про 2.x.

Какие книги?

«Data Pipelines with Apache Airflow» (Harenslak) — главная книга. Также официальная документация.

Сколько готовиться к Airflow-блоку?

С нуля — 1-2 месяца с практикой. Уже работал — 2-4 недели.

Спрашивают ли scheduler internals?

На senior — да. На middle — общее понимание (DAG parsing, scheduler/worker разделение).

Смотрите также