Пайплайн данных это цепочка шагов: забрать, проверить, преобразовать, загрузить. Оркестратор запускает шаги по расписанию и в нужном порядке, повторяет упавшие и показывает, что сломалось. Самый распространённый оркестратор в РФ и в мире: Apache Airflow.
ETL и ELT
- ETL (extract, transform, load): данные преобразуются до загрузки в хранилище, на отдельном сервере или кластере. Классика времён дорогих хранилищ.
- ELT (extract, load, transform): данные загружаются как есть в сырой слой, а преобразования выполняются SQL внутри хранилища (часто через dbt). Стал стандартом с появлением мощных облачных и колоночных хранилищ.
Плюсы ELT: сырые данные сохранены, логику можно поменять и пересчитать, преобразования на SQL понятны аналитикам. ETL остаётся уместным, когда данные надо очистить или обезличить до попадания в хранилище.
Главные свойства хорошей задачи
- Идемпотентность: повторный запуск за тот же период даёт тот же результат. Вместо «дописать» используем «перезаписать партицию за период» или upsert по ключу.
- Детерминированный период: задача обрабатывает свой интервал данных, а не «всё, что пришло с прошлого раза» и не «данные за вчера относительно текущего времени».
- Атомарность: запись в промежуточное место и атомарная подмена (swap партиции, транзакция), чтобы читатели не видели половину данных.
- Ретраи с паузой для временных сбоев источника.
Эти свойства делают возможным бэкфилл: пересчёт истории за прошлые периоды тем же кодом.
Airflow: основные понятия
- DAG: направленный ациклический граф задач с расписанием. Описывается кодом на Python.
- Task: узел графа. Создаётся из оператора:
BashOperator,PythonOperator, операторы провайдеров (Postgres, S3, Spark, Kubernetes) или через TaskFlow API с декоратором@task. - Sensor: задача, которая ждёт условия: файл появился, партиция готова, внешний DAG завершился. Режим
rescheduleосвобождает слот воркера между проверками. - DAG run: один запуск DAG за конкретный интервал данных. Task instance: запуск задачи в рамках DAG run.
- XCom: обмен небольшими значениями между задачами (id, путь к файлу). Не для передачи датафреймов: XCom хранится в метабазе.
- Pool и параллелизм: ограничение одновременных задач, чтобы не перегрузить источник.
- Connections и Variables: параметры подключений и настройки вне кода; пароли не хранятся в коде DAG.
Интервалы данных и логическая дата
Каждый запуск привязан к интервалу данных data_interval_start и data_interval_end и к логической дате (logical_date, в Airflow 2 ещё называлась execution_date, в Airflow 3 старое имя убрано). Для ежедневного интервального расписания запуск за 1 сентября стартует после окончания интервала, то есть 2 сентября в 00:00: данные за день должны успеть накопиться. Это частый вопрос на собесе. В Airflow 3 для cron-расписаний по умолчанию поменялась логика интервалов, поэтому смотрите, как ведёт себя ваша версия, и в коде задач опирайтесь на data_interval_start и data_interval_end, а не на datetime.now().
Catchup: если у DAG start_date в прошлом, Airflow создаст запуски за все пропущенные интервалы. Иногда это нужно (бэкфилл), иногда нет. Значение по умолчанию отличается между версиями и настройками, поэтому задавайте catchup явно.
Чего не делать в коде DAG
- Тяжёлые вычисления и запросы к базе на верхнем уровне файла: планировщик постоянно перечитывает файлы DAG, и такой код выполняется при каждом разборе.
- Динамическое
start_dateвродеdatetime.now(): расписание становится непредсказуемым. - Обработка данных на воркере Airflow: Airflow оркестрирует, а тяжёлую работу делают Spark, хранилище, Kubernetes-поды.
- Передача больших данных через XCom.
- Пароли в коде.
Зависимости между DAG
Варианты: сенсор на внешний DAG или задачу, datasets (в Airflow 3 называются assets): DAG запускается, когда обновился набор данных, который производит другой DAG. Data-aware scheduling лучше хрупких расписаний «этот в 2:00, тот в 3:00, надеемся успеет».
Альтернативы
Dagster (ориентирован на ассеты данных), Prefect, Argo Workflows для Kubernetes. На собесе полезно знать, что они существуют и чем отличаются, но спрашивают в основном Airflow.
Частые ошибки
- Задача пишет «за вчера» через текущее время: бэкфилл и перезапуски считают не те данные.
INSERTбез очистки периода: дубли после ретрая.- Сенсоры в режиме
pokeзанимают все слоты воркеров. - Один гигантский DAG на всё: падение одной ветки блокирует остальные.
Что спросят на собесе
- ETL против ELT.
- Что такое идемпотентная задача и как её сделать.
- DAG, оператор, сенсор, XCom; чего не делать в коде DAG.
- Логическая дата и интервал данных, когда стартует запуск за 1 сентября.
- Catchup и бэкфилл.