Почему кэширование небольших RDD Spark требует большого объема памяти в Yarn?

Кэшированные RDD (всего 8) невелики, всего около 30 ГБ, однако в пользовательском интерфейсе Hadoop это показывает, что приложение Spark занимает много памяти (активные задания не выполняются), т.е. 1,4T, почему так много?

введите описание изображения здесь

введите описание изображения здесь

Почему он показывает около 100 исполнителей (здесь, то есть vCore), даже когда нет активных заданий?

Кроме того, если кэшированные RDD хранятся у 100 исполнителей, сохраняются ли эти исполнители, и никакие другие приложения Spark больше не могут использовать их для выполнения задач? Перефразируя вопрос: будет ли сохранение небольшого ресурса памяти (.cache) в исполнителях препятствовать тому, чтобы другое приложение Spark использовало их простаивающие вычислительные ресурсы?

Есть ли какая-нибудь потенциальная конфигурация Spark config / zeppelin, которая может вызвать это явление?


ОБНОВЛЕНИЕ 1

После проверки Spark conf (zeppelin) кажется, что есть настройка по умолчанию (настроенная администратором по умолчанию) для spark.executor.memory=10G, что, вероятно, является причиной.

Однако здесь возникает новый вопрос: можно ли сохранить только память, необходимую для кэшированных RDD в каждом исполнителе, и освободить остальные вместо того, чтобы всегда хранить изначально установленную память spark.executor.memory=10G?

Конфигурация Spark

введите описание изображения здесь


person jack    schedule 22.12.2020    source источник
comment
Потребление памяти может быть связано со многими причинами - кэшированные RDD - это только его часть. Если вы хотите уменьшить использование памяти, вы можете попробовать установить для spark.executor.memory более низкое значение.   -  person mck    schedule 22.12.2020
comment
@mck Спасибо. Что еще может увеличить объем памяти до 1,4 ТБ, если никакие задания не выполняются И кешированные RDD настолько малы?   -  person jack    schedule 22.12.2020
comment
предыдущие выполняемые задания могут иметь несобранный мусор   -  person mck    schedule 22.12.2020
comment
@mck Верно, это вдохновляющие подсказки, разве Spark не должен делать сборщик мусора автоматически, или есть способ запустить сборщик мусора пользователями? Я полагаю, что это обычная проблема, и она серьезная, поскольку занимает так много ресурсов после запуска приложения.   -  person jack    schedule 22.12.2020
comment
Я не уверен, по моему опыту он имеет тенденцию собирать мусор, когда ему не хватает памяти. Если вы дадите ему 1T, он просто будет использовать все, пока не закончится место.   -  person mck    schedule 22.12.2020
comment
В моем случае кажется, что нет, другие приложения Spark просто заблокированы из-за этого, они ждут, пока мое приложение освободит ресурс, убивая его вручную .. Кого мы должны винить? Моя конфигурация приложения Spark, Yarn или Hadoop? Кто заботится об этом аспекте?   -  person jack    schedule 22.12.2020
comment
Полагаю виноват конфиг. Я предполагаю, что конфигурация - это 1T памяти, поэтому каждое приложение Spark считало, что у них есть 1T для использования, но на самом деле они используют 1T, что заставляет их бороться. Возможно, лучше указать 100 ГБ для каждого приложения, если вам нужно запустить несколько приложений.   -  person mck    schedule 22.12.2020
comment
@mck Я не установил конкретную конфигурацию для spark.executor.memory, и я предполагаю, что приложение будет занимать память любого размера, которая ему нужна, что нормально для кластера (поскольку у нас есть этот ресурс), но после завершения я бы хотел, чтобы оно освободило занятый ресурс, который был использован. Поэтому я не хочу ограничивать spark.executor.memory, поскольку нет смысла ограничивать, если это необходимо при выполнении заданий, но освобождение после его завершения - это абсолютно желательно. На самом деле хочу знать, как добиться ..   -  person jack    schedule 22.12.2020
comment
как насчет вызова spark.stop после завершения работы приложения ...?   -  person mck    schedule 22.12.2020
comment
Мне понадобятся cached RDD для интерактивной аналитики, поэтому я cache, чтобы избежать повторных вычислений. Но я бы хотел, чтобы Spark сохранял только память, используемую для кеширования после завершения вычислений, и позволял всем остальным уйти, не будучи жадным - я думаю, это то, с чем Spark должен быть в состоянии справиться, не так ли?   -  person jack    schedule 22.12.2020
comment
Я не знаю ответа, но это определенно звучит как идеальный случай :)   -  person mck    schedule 22.12.2020
comment
@jack можешь поделиться конфигом.   -  person Chandan    schedule 25.12.2020
comment
@Chandan Только что добавлено под вопрос   -  person jack    schedule 25.12.2020


Ответы (2)


Возможно, вы можете попробовать repartition(n) ваш RDD на меньшее количество n < 100 разделов перед кэшированием. RDD размером ~ 30 ГБ, вероятно, поместится в память десяти исполнителей по 10 ГБ. Хороший обзор управления памятью Spark можно найти здесь. Таким образом, только те исполнители, которые содержат кешированные блоки, будут прикреплены к вашему приложению, а остальные могут быть возвращены YARN через динамическое выделение Spark после spark.dynamicAllocation.executorIdleTimeout (по умолчанию 60 секунд).

В: Можно ли сохранить только память, необходимую для кэшированных RDD в каждом исполнителе, и освободить остальные вместо того, чтобы всегда сохранять изначально установленную память spark.executor.memory = 10G?

Когда Spark использует YARN в качестве механизма выполнения, YARN выделяет контейнеры указанного (по приложению) размера - не менее spark.executor.memory+spark.executor.memoryOverhead, но может быть даже больше в случае pyspark - для всех исполнителей. Сколько памяти Spark фактически использует внутри контейнера, становится неактуальным, поскольку ресурсы, выделенные контейнеру, будут считаться недоступными для других приложений YARN.

person mazaneicha    schedule 29.12.2020
comment
Спасибо за совет. Я попробовал df.repartitionByRange(4, col("key")), а затем инициировал действие, но я все еще вижу, что Распределение данных на 100 исполнителей в пользовательском интерфейсе хранилища, а Yarn по-прежнему показывает 101 исполнитель, есть идеи, почему не удалось переразбить? - person jack; 30.12.2020
comment
Вы уверены, что ваше действие кэширует перераспределенный набор данных, а не перераспределяет кешированный набор данных? Порядок важен ... :) - person mazaneicha; 30.12.2020
comment
Я unpersist кеширую df / rdd, repartition df / rdd и cache и снова запускаю действие, затем оно уменьшает nb. исполнителей занято. Лучшим решением может быть использование coalesce, так как это позволит избежать ненужного перетасовки IMO. - person jack; 31.12.2020
comment
Иногда, даже после того, как repartition используется и только 1 исполнитель удерживает кешированный элемент, 20 исполнителей все еще находятся в состоянии ALIVE и ничего не делают! Должен ли я явно убить их? Почему Spark не перерабатывает их? Ожидается ли это? - person jack; 31.12.2020
comment
@jack, исполнители живы, потому что действие помечается как завершенное, когда все задачи завершены. Таким образом, если у одной задачи больше данных, другие будут просто ждать ее завершения. Вот почему так важно каким-то образом перераспределить данные. Даже при включенном динамическом распределении задачи не будут отправляться другим действиям, поэтому единственный выбор здесь - установить равномерное распределение данных. - person Oscar Lopez M.; 31.12.2020
comment
@jack, который звучит неправильно, обычно вы должны видеть, что количество исполнителей уменьшается до spark.dynamicAllocation.minExecutors (после тайм-аута простоя). Итак, происходит что-то еще, и вам, вероятно, потребуется просмотреть журнал драйверов, чтобы понять, почему он не дает им команду на выключение. - person mazaneicha; 31.12.2020

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

  • Если вы читаете файлы Parquet или CSV, убедитесь, что они имеют одинаковый размер. Запуск repartition() вызывает перемешивание, которое, если данные настолько искажены, может вызвать другие проблемы, если у исполнителей недостаточно ресурсов.
  • Кэш не поможет освободить память исполнителям, потому что он не перераспределяет данные
  • Не могли бы вы увидеть в разделе «Временная шкала событий на этапах», насколько велики зеленые полосы? Обычно это связано с распределением данных, так что это способ увидеть, сколько данных загружено (пропорционально) для каждой задачи и сколько они делают. Поскольку всем задачам назначена одинаковая память, вы можете графически увидеть, потрачены ли ресурсы впустую (в случае, если есть в основном крошечные полосы и несколько больших полос). Образец потраченных впустую ресурсов можно увидеть на изображении ниже.

введите описание изображения здесь

Есть разные способы создания равномерно распределенных файлов для вашего процесса. Я упоминаю некоторые возможности, но наверняка их больше:

  • Использование Hive и предложения DISTRIBUTE BY: вам нужно использовать поле, которое одинаково сбалансировано, чтобы создать столько файлов (и с надлежащим размером), сколько ожидалось.
  • Если процесс создания этих файлов является процессом Spark, считывающим из БД, попробуйте создать столько подключений, сколько файлов вам нужно, и используйте правильное поле для заполнения разделов Spark. Это достигается, как объясняется здесь и здесь со свойствами partitionColumn, lowerBound, upperBound и numPartitions
  • Повторное разделение может работать, но посмотрите, имеет ли смысл объединение в вашем процессе или в предыдущем, генерирующем файлы, из которых вы читаете
person Oscar Lopez M.    schedule 29.12.2020
comment
Спасибо за точку coalesce! - person jack; 31.12.2020
comment
@jack, это не проблема. Посмотрите, сможете ли вы каким-либо образом перераспределить свои данные, чтобы снизить требования к памяти для исполнителей. - person Oscar Lopez M.; 31.12.2020
comment
См. Мой комментарий в ответе выше о том, что исполнители являются ALIVE, есть идеи по этому поводу? - person jack; 31.12.2020
comment
ответил выше, так как это где комментарий :). Спасибо, что указали мне туда! - person Oscar Lopez M.; 31.12.2020