Искробезопасность: что я делаю неправильно?

Я обрабатываю данные с помощью искры, и он работает с деньгами данных (40G), но не работает с OOM на неделю:

import pyspark
import datetime
import operator
sc = pyspark.SparkContext()
sqc = pyspark.sql.SQLContext(sc)
sc.union([sqc.parquetFile(hour.strftime('.....'))
          .map(lambda row:(row.id, row.foo))
          for hour in myrange(beg,end,datetime.timedelta(0,3600))]) \
  .reduceByKey(operator.add).saveAsTextFile("myoutput")

Количество разных идентификаторов меньше 10k. Каждый идентификатор является маленьким int. Работа завершается неудачно, потому что слишком много исполнителей не работают с OOM. Когда задание выполняется успешно (на небольших входах), "myoutput" составляет около 100 тыс.

  • Что я делаю неправильно?
  • Я попытался заменить saveAsTextFile на collect (потому что на самом деле я хочу сделать некоторые нарезки и нарезки в python перед сохранением), не было никакой разницы в поведении и в том же отказе. это следует ожидать?
  • Раньше я имел reduce(lambda x,y: x.union(y), [sqc.parquetFile(...)...]) вместо sc.union - что лучше? В чем разница?

В кластере есть 25 узлы с оперативной памятью 825 ГБ и 224.

Вызов spark-submit --master yarn --num-executors 50 --executor-memory 5G.

Один RDD имеет ~ 140 столбцов и охватывает один час данных, поэтому неделя представляет собой объединение 168 (= 7 * 24) RDD.

Ответ 1

Spark очень часто страдает от ошибок Out-Of-Memory при масштабировании. В этих случаях тонкая настройка должна выполняться программистом. Или перепроверьте свой код, чтобы убедиться, что вы ничего не делаете слишком много, например, соберите все bigdata в драйвере, который, скорее всего, превысит ограничение memoryOverhead, независимо от того, насколько вы его настроили.

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

В Планировщике вы можете проверить временную шкалу событий, чтобы узнать, что произошло с контейнерами. Если Yarn убил контейнер, он будет красным, и когда вы нажмете/нажмете на него, вы увидите сообщение типа:

Контейнер, убитый YARN, превышает пределы памяти. Используется 16,9 ГБ физической памяти 16 ГБ. Подумайте о том, как активировать spark.yarn.executor.memoryOverhead.

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


Итак, в этом случае вы хотите сосредоточиться на этих свойствах конфигурации (значения приведены в моем кластере):

# More executor memory overhead
spark.yarn.executor.memoryOverhead          4096

# More driver memory overhead
spark.yarn.driver.memoryOverhead            8192

# Max on my nodes
#spark.executor.cores                        8
#spark.executor.memory                       12G

# For the executors
spark.executor.cores                        6
spark.executor.memory                       8G

# For the driver
spark.driver.cores                          6
spark.driver.memory                         8G

Первое, что нужно сделать, - это увеличить memoryOverhead.

В драйвере или в исполнителях?

Когда вы просматриваете свой кластер из пользовательского интерфейса, вы можете щелкнуть идентификатор попытки и проверить информацию диагностики, которая должна содержать идентификатор убитого контейнера. Если это то же самое, что и в вашем контейнере AM, то это драйвер, иначе исполнитель (и).


Это не решило проблему, теперь что?

Вы должны точно настроить количество ядер и память кучи, которые вы предоставляете. Вы видите будет выполнять большую часть работы в памяти кучи, поэтому вы не хотите оставлять слишком много места для кучи, так как это будет потрачено впустую. Вы не хотите давать слишком меньше, потому что у сборщика мусора будут проблемы. Напомним, что это JVM.

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

Я написал это в memoryOverhead проблема в Spark и Spark - Контейнер вышел с ненулевым кодом выхода 143 более подробно, в основном, что я не забуду! Другой вариант, который я не пробовал, будет spark.default.parallelism или/и spark.storage.memoryFraction, который, основываясь на моем опыте, не помог.


Вы можете передавать флаги конфигурации как упомянутые sds или как это:

spark-submit --properties-file my_properties

где "my_properties" - это что-то вроде перечисленных выше атрибутов.

Для не численных значений вы можете сделать это:

spark-submit --conf spark.executor.memory='4G' 

Ответ 2

Оказалось, что проблема была не в искре, а в пряжи. Решение состоит в том, чтобы запустить искру с помощью

spark-submit --conf spark.yarn.executor.memoryOverhead=1000

(или изменить конфигурацию пряжи).