Руководство, как стать дата-инженером от инженера-программиста.

Это руководство поможет вам стать инженером данных из инженера-программиста и расскажет, как PySpark заставляет вас думать иначе, чем вы, работая бэкэнд-инженером.

Инжиниринг данных — это новая горячая тенденция в программном обеспечении в наши дни. Поскольку каждый день создается все больше и больше данных, и все больше и больше компаний также используют эти данные, существует огромная потребность в инженерах данных. Но в большинстве случаев инженеров общего профиля гораздо больше, чем инженеров данных. Как люди и компании могут переходить от одного к другому?

В этой статье будет представлен обзор некоторых различий, общих черт и того, какой образ мышления вы должны принять в качестве инженера данных. В статье основное внимание будет уделено Python и PySpark, но многие идеи также переносятся на Java/Scala и другие фреймворки.

Обо мне

Я работаю инженером по программному обеспечению/данным в Klarna чуть больше года. Наша команда предоставила данные для включения функции поиска в приложении. Мы собрали данные о продуктах, унифицировали формат, проверили и дополнили его для более чем 10 миллионов продуктов каждые пару часов.

До Klarna я работал с Django и Angular. Только в Klarna я начал работать с «большими» данными и принципами проектирования данных. Моя команда состояла из 5 инженеров по бэкенду и 2 инженеров по данным, поэтому нам пятерым нужно было быстро изучить, чем занимаются инженеры по данным.

Начиная

Сбор данных

Первая часть инженерии данных — это получение данных. Для этого вы можете использовать HTTP, (S)FTP, API, события... Все это очень стандартные реализации Python, ничего такого, чего бы вы не сделали как бэкэнд-разработчик. Единственная разница может заключаться в том, что масштаб больше. Но он по-прежнему просто использует вычислительные экземпляры или бессерверные функции и т. д.

ETL малого масштаба

После сбора данных у нас есть обработка данных, часто ETL (Extract Transform Load) или ELT (Extract Load Transform). Обычный бэкенд-инженер также может сделать это в ванильном Python, например, со словарями. Но когда ваши данные становятся большими (от гигабайтов до терабайтов), их становится очень сложно масштабировать.

Добро пожаловать

При масштабировании неизбежно необходимо учитывать (Py)Spark. Spark может обрабатывать миллионы строк за пакетное задание быстрее и намного эффективнее, чем обычное пакетное задание. Хотя запуск кластера PySpark сложен, вы также можете получить его без сервера (например, AWS Glue) или поручить управление кластером более специализированным инженерам.

Во многих отношениях PySpark — это просто библиотека Python (поверх среды выполнения Java, но это можно игнорировать). Так что сначала вы также можете использовать его как библиотеку. Он предоставляет классы, функции, операторы… Вы можете просто просмотреть документацию в Интернете, но лучший способ научиться — это сделать это. В основном это будет работать как гигантская пакетная работа. С таким мышлением вы не получитеPySpark и не будете использовать его потенциал, но он будет работать.

Понимание PySpark

В какой-то момент PySpark-как-библиотека достигнет своих пределов. Ваша работа занимает много времени, добавление дополнительных узлов или памяти не сильно поможет, и все остановится. На этом этапе вы должны узнать, как работает PySpark.

Самое важное, что вам нужно понять, это узлы и разделы.

Узлы

PySpark управляется в разных узлах, в основном в разных вычислительных экземплярах. Один узел является главным узлом и управляет другими узлами, вычислительными узлами. Данные разбиваются по разделам и отправляются на узлы.

Одна только эта причина делает очень важным создание хороших и сбалансированных разделов. Таким образом, каждый узел получит одинаковое количество данных и займет одинаковое количество времени.

Поскольку каждый узел имеет свои собственные данные, любая операция только с этими данными выполняется очень быстро. PySpark также будет распараллеливать эти операции внутри для повышения производительности. Примерами являются сложение, выборка из списков, регулярные выражения… Но также подходят агрегаты внутри узла. Например, если каждая страна находится в узле, вы можете легко подсчитать количество строк в стране.

Перегородки

Разделение – это выбор данных, в какие узлы они попадают. Поскольку совместное использование данных между экземплярами является медленным и дорогим, важно выбрать способ разделения.

Полезно знать, что в узле может быть более одного раздела. Таким образом, вам не нужно иметь одинаковое количество разделов и узлов. Однако ваши разделы не должны быть слишком маленькими или слишком большими. Слишком маленькие разделы слишком сильно разбивают ваши данные и снижают эффективность. Слишком большие разделы не поместятся в узле, что приведет к сбою процесса или неиспользованию всех ваших узлов. Идеальным размером раздела считается 100–200 Мб.

Первый способ секционирования — это секционирование по дате или времени. Об этом очень легко думать, и часто каждый день имеет одинаковое количество операций.

Другой способ - использовать разбиение по регионам или странам, если у вас есть такая информация. Хотя в США и Бельгии не будет одинакового размера набора данных, операции часто выполняются в одной стране, поэтому их можно легко выполнять.

Третий способ разбиения — это синтетическое разбиение, например, взятие по модулю идентификатора. Хотя таким образом вы можете создать однородный раздел нужного размера, операции внутри раздела не имеют смысла.

Отличие от баз данных

Эти узлы и разделы изменят ваш способ разработки.

Прежде всего, вы хотите максимально избежать перетасовки или обмена данными между разделами. Всякий раз, когда вы хотите поделиться данными или объединить данные, как правило, лучше сделать это один раз, с минимальным объемом данных.

Для сбора и группировки данных, как правило, лучше всего делать это как можно позже. И если вы хотите сделать это несколько раз, рекомендуется кэшировать последние общие данные, чтобы PySpark мог повторно использовать эти данные вместо их пересчета.

Это означает, что вам нужно мыслить разделами и узлами, а не строками. Не выполняйте операции построчно, а раздел за разделом.

Работа с данными

Вторым большим отличием будет ваш рабочий процесс разработки во время разработки. В стандартном бэкэнд-инжиниринге у вас есть код, вы его запускаете (python main.py) и живете счастливой жизнью. При использовании (Py)Spark это усложняется.

Разработка

При разработке вы хотите запустить код, который вы создаете, чтобы убедиться, что он правильный. Или при отладке вы хотите имитировать ошибку, запустив то же самое.

Однако с большими данными ваша машина может не работать должным образом. Или у вас нет такого же доступа к облачным ресурсам, чтобы иметь возможность запускать все правильно. В частности, для Python интерпретатор часто не находит правильный процесс Spark для отправки своих инструкций.

Одним из решений является использование онлайн-среды. Мы использовали AWS Glue, управляемую бессерверную среду PySpark. Glue предлагает Конечные точки разработки, которые предлагают онлайн-среду. При необходимости вы можете масштабировать их вверх и вниз и предлагает похожую, но не идентичную среду, в которой выполняется ваш производственный код.

У этой конечной точки разработки есть свои проблемы, такие как стоимость, дополнительные библиотеки и отсутствие надлежащих версий PySpark, и мы старались избегать этого, когда это было возможно. В конце концов я выбрал либо написание тестов для запуска кода, либо запуск задания в облаке и просмотр логов. Он не допускает отладки и не идеален, но работает. ¯\_(ツ)_/¯

Наконец, отладка поддерживается не везде. Поскольку все в узлах выполняется в отдельных процессах, точки останова в этих функциях не работают. Таким образом, вы можете проверять только вывод между каждым шагом, а не фактическую обработку разделов. Это делает функции отладки очень раздражающими, особенно для пользовательских функций.

Тестирование

Каждый хороший фрагмент кода нуждается в тестировании, и инженерия данных ничем не отличается. Но поскольку мы используем PySpark, у нас возникает дополнительная сложность. К сожалению, PySpark работает не только с pip install pyspark

У AWS Glue есть хорошая статья о том, как заставить PySpark работать локально здесь. Некоторые другие шаги включают в себя: наличие правильной версии Java (Java JDK 8), наличие Spark (ubuntu) и установка SPARK_HOME. Используя PyCharm, он работает довольно хорошо.

К сожалению, PySpark довольно медленно запускается, поэтому автозапуск тестов для них не очень удобен. Обычный питон по-прежнему остается обычным питоном и довольно быстр. Итак, мы разделили тесты на 3 разных типа: функциональные/модульные тесты, которые проверяют необработанную функцию и код Python; Тесты Spark, которые проверяют определенный фрагмент кода Spark, например объединение, пользовательские функции или правильное сопоставление; и тесты преобразования, которые проверяют весь поток данных с помощью фиктивных данных.

Наконец, конвейеры данных имеют множество входов и выходов, и многое может пойти не так при настройке проводки. Поскольку мы были на 100 % бессерверными, мы решили создать комплексные тесты инфраструктуры. Они создают совершенно новый стек, пропускают через него некоторые образцы данных и смотрят, есть ли у нас правильный вывод. Поскольку это довольно сложно, мы ограничились тем, чтобы убедиться, что у нас есть некоторый вывод, а не проверять точные данные. Это обеспечит правильное подключение всех наших компонентов. Наши тесты на преобразование помогут убедиться, что данные верны.

Заключение

Инжиниринг данных отличается от стандартного бэкэнд-инжиниринга, но ненамного. Вы можете начать легко, не слишком заботясь о масштабе и писать так, как вы обычно пишете. При масштабировании важно узнать о мелких и важных деталях PySpark или любого другого инструмента.

Я считаю, что любой бэкэнд-программист может перейти к разработке данных, если захочет. Хотя я бы посоветовал иметь опытных дата-инженеров, которые помогут вам преодолеть сложности.

Спасибо за чтение.

Больше контента на plainenglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку здесь.