Как понять, что ETL-конвейер работает неправильно
Почему конвейеры данных отказывают незаметно, какие признаки отслеживать и как выстроить мониторинг до того, как проблема появится в управленческом отчёте.
Большинство ETL-конвейеров отказывают тихо. Задача не выдаёт ошибку, логи выглядят чистыми, планировщик показывает «выполнено успешно» - но данные, попавшие в хранилище, неверны. Частичны. Задублированы. Устарели на три дня. Никто не замечает, пока менеджер не спрашивает, почему цифры прошлой недели не совпадают с тем, что показывает CRM.
Я видел этот паттерн достаточно часто, что теперь воспринимаю «наши конвейеры работают и мы получаем оповещения при сбоях» как нижнюю планку, а не потолок того, что должен охватывать мониторинг дата-инфраструктуры. ETL-конвейер ведёт себя как производственная линия с очередями, простоями и невидимыми серыми операциями - и мониторинг должен это отражать.
Почему тихие отказы - норма
ETL-задачи создаются устойчивыми. Хорошо написанная задача обрабатывает таймауты соединений, повторяет неудавшиеся запросы и логирует то, что не смогла обработать, прежде чем завершиться. Это правильное поведение с точки зрения доступности. Проблема в том, что «завершено с пропуском нескольких записей» выглядит в логе успеха точно так же, как «завершено с обработкой всех записей».
Исходные системы меняются без предупреждения. Поставщик обновляет API, и поле, которое раньше хранило числовое значение, теперь содержит строку. Конвейер не падает - он молча отбрасывает строки, которые не может разобрать, или, что хуже, приводит значение к чему-то похожему на правдоподобное, но неверному.
Дрейф схемы - самая распространённая форма этого. Конвейер был построен под исходную систему в том виде, в каком она существовала, когда кто-то писал ETL-код. С тех пор исходная система прошла несколько релизов. Технический долг в data-пайплайнах накапливается незаметно, а «потом перепишем» почти никогда не происходит - дрейф схемы без контроля именно так превращает конвейеры в постоянно сломанные системы, которые никто не признаёт сломанными.
Что на самом деле охватывает полезный мониторинг
Мониторинг на уровне задач - «задача запустилась, завершилась, сколько времени заняла» - необходим, но недостаточен. Мониторинг, который выявляет реальные проблемы, работает на уровне данных:
Количество строк в сравнении с базовым значением или с тем, что сообщает исходная система. Задача, обрабатывающая 40 000 записей в один день и 400 - в следующий, либо имела очень тихий день выше по потоку, либо потеряла 99% данных. Без проверки количества строк это различие невидимо, пока кто-то не заметит.
Доля нулей в полях, которые не должны быть нулевыми. Если поле «ID клиента» начинает приходить с 15% нулей при прежних 0%, что-то изменилось выше по потоку.
Проверки актуальности. Таблица, которая должна обновляться каждые четыре часа, должна иметь проверку, срабатывающую, когда самая свежая запись шестичасовой давности. Не всё должно быть в реальном времени, но у всего должна быть известная ожидаемая свежесть и монитор, замечающий её нарушение.
Проверки распределения значений для полей с известным ожидаемым диапазоном. Поле суммы заказа, внезапно содержащее нулевые или отрицательные значения в наборе данных, где их ранее не было, - признак, заслуживающий изучения.
Вопрос порогов
Не каждая аномалия должна будить кого-то в три ночи. Вопрос проектирования мониторинга - о порогах и маршрутизации: какие условия достаточно серьёзны для прерывания производства, какие должны отражаться в утреннем отчёте, а какие могут ждать еженедельного обзора.
Обычно я начинаю с: всё, что делает отчёты незаметно неверными, должно создавать оповещение до следующего чтения этих отчётов. Всё остальное может быть менее срочным.
Поэтапное выстраивание
Не нужно инструментировать всё сразу. В новой дата-среде я нахожу полезным начинать с трёх-четырёх таблиц, которые питают отчёты, реально используемые менеджментом для принятия решений. Это места, где тихий отказ имеет наиболее видимые последствия, и обычно это небольшая доля всего конвейера.
Начните там с проверок количества строк и актуальности. Добавьте проверки нулей и распределения там, где исходные системы заведомо нестабильны. Когда базовый уровень заработает - распространите его на остальной конвейер.
Цель - не достичь теоретического покрытия каждого возможного режима отказа. Цель - убедиться, что данные, на основе которых принимаются решения, - это именно те данные, которые вы думаете.