Комментарии 9
нехорошо копирайты на чужих картинках вырезать
Ну например, в моем понимании, компонент приложения для спарка должен выглядеть не как нечто, принимающее на входе таблицу и выдающее таблицу, а как Dataset->Dataset. Почему? Да потому что Dataset->Dataset например проще тестировать. А именно, это приводит нас к тому, что код, который строит Dataset из таблицы (или файлов в HDFS, к примеру) должен быть отделен от кода, который Dataset трансформирует. Тогда тестирование не завязано на наличие Hive и таблиц, и может быть проведено на модельных данных, включая условия как на схему построенного датасета, так и на данные.
Вот что-то такое для нас является мотивом выбора архитектуры. Тут этого увидеть не удалось. Точнее, многие идеи показались не просто знакомыми, а прям родными — но все это слегка размазано по тексту, не хватило какой-то выжимки возможно, хотя пост в целом скорее понравился.
Ну и так, в качестве мелкой придирки — миллиарды строк вообще говоря не признак больших данных само по себе. Все-таки, они такими становятся, когда перестают влезать в память, или в хранилище, и требуют другого способа обработки. Скажем, у нас в хадупе тоже есть таблицы на много миллиардов, или скажем десятки терабайт изменений в сутки — но если взглянуть с другой стороны, то они же приходят к нам в хадуп из Оракла, то есть они вполне себе обрабатываются там в обычной реляционной СУБД.
Спасибо за развёрнутый комментарий!
Данная структура позволяет работать в концепции Dataset->Dataset, но при этом позволяет и общаться с базами напрямую и не плодить функции загрузки таблиц. Также, при загрузке таблицы из базы, она ещё проверит колонки-типы таблицы на соответствие описанию. Что придаёт чуточку больше стабильности.
Помимо разделения расчётов и выгрузок, архитектура нацелена на разбиение самих расчётов на логические шаги небольшого размера с понятным описанием входов и выходов. То есть при попытке понять, что происходит на определённом шаге алгоритма, не нужно прослеживать все предшествующие операции, чтобы разобраться в структурах таблиц, используемых в расчётах, достаточно посмотреть описание.
Ну и наконец, автоматическая сборка документации в понятном виде также являлась важным моментом для нашего проекта. Представленная архитектура позволяет собирать такую документацию достаточно легко.
Опять же оговорюсь, что цель статьи не пропаганда "наилучшего" подхода, а просто демонстрация рабочего и, как нам показалось, удобного.
P.S. по вопросу больших данных спорить не буду, понятие настолько же определённое, насколько размытое)
То что вы пишете, например о проверке схем между шагами, проверках соответствия документации (т.е. ожиданиям) — это прям тоже самое, чем мы занимаемся у себя (у нас еще процесс включает преобразования типов данных колонок, причем описанные пользователями на некотором языке, поэтому получить на выходе строку вместо числа — в теории возможно, и схему результата на это тоже нужно контролировать). То есть это все более чем логично.
Согласен с вами. В работе стараюсь придерживаться изоляции разных "стадий" жизни приложения, т.к. хоть проекты могут быть разными, но структура по сути одна и та же:
читаем из источника
применяем трансформации
пишем куда-либо
А если глобально в приложении, то:
инициализируем контекст
инициализируем конфигурацию (обычно мы используем внешний Key-Value, но есть варианты с SQL/JSON)
запускаем препроцессинг/процессинг/постпроцессинг (если это нельзя разделить по разным приложениям)
сохраняем статус во внешнем простом хранилище (файлы, бд или API)
Это конечно в общем и пальцем в небо и секрета тут никакого нет совсем, но позволяет покрывать тестами без каких-либо проблем все трансформации, что у нас есть.
Чтение и запись мы уже, конечно, покрываем с использованием Mock.
А вот все лишние обвязки мы стараемся убрать совсем, поэтому я не понял, зачем в статье упоминается pandas, но это, мне кажется, мелочи.
А идея автора в общем состоит в том, если ее упростить, что последовательность неких преобразований описывается конфигом, который является и документацией в тоже время. У нас скажем чуть иначе, и мы скорее движемся к некоторому DSL, который будет описывать трансформации, потому что у нас сама логика трансформации может зависеть в широких пределах от разных параметров, и проще это не в виде конфига описать, а скриптом (хотя понятно, что документацию из конфига извлекать проще — но нам это не нужно). Ну т.е. по сути, у нас есть определенный набор трансформаций, каждая из которых может быть видоизменена под требования конкретного пайплайна. Вот они и пишутся на языке типа груви или скалы в терминах датасетов, и им предоставляется наш API для получения информации для принятия решений.
Хорошо, что у нас только фиксированные трансформации :) правда, как раз на питоне
Построение архитектуры проекта при работе с PySpark