Как избежать того, чтобы исполнитель Spark потерял и уничтожил контейнер из пряжи из-за ограничения памяти?

У меня есть следующий код, который запускает hiveContext.sql() большую часть времени. Моя задача: я хочу создать несколько таблиц и вставить значения после обработки для всего раздела таблицы hive.

Поэтому я сначала запускаю show partitions и используя его вывод в цикле for, я вызываю несколько методов, которые создают таблицу (если она не существует) и вставляются в них с помощью hiveContext.sql.

Теперь мы не можем выполнить hiveContext в исполнителе, поэтому я должен выполнить это в цикле for-loop в программе драйвера и выполнять поочередно поочередно. Когда я отправляю эту работу Spark в кластер YARN, почти все время мой исполнитель теряется из-за того, что shuffle не найден исключение.

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

Будет ли следующий код делать все параллельно и попытаться одновременно разместить все данные раздела кустов в памяти?

public static void main(String[] args) throws IOException {   
    SparkConf conf = new SparkConf(); 
    SparkContext sc = new SparkContext(conf); 
    HiveContext hc = new HiveContext(sc); 

    DataFrame partitionFrame = hiveContext.sql(" show partitions dbdata partition(date="2015-08-05")"); 
  
    Row[] rowArr = partitionFrame.collect(); 
    for(Row row : rowArr) { 
        String[] splitArr = row.getString(0).split("/"); 
        String server = splitArr[0].split("=")[1]; 
        String date =  splitArr[1].split("=")[1]; 
        String csvPath = "hdfs:///user/db/ext/"+server+".csv"; 
        if(fs.exists(new Path(csvPath))) { 
            hiveContext.sql("ADD FILE " + csvPath); 
        } 
        createInsertIntoTableABC(hc,entity, date); 
        createInsertIntoTableDEF(hc,entity, date); 
        createInsertIntoTableGHI(hc,entity,date); 
        createInsertIntoTableJKL(hc,entity, date); 
        createInsertIntoTableMNO(hc,entity,date); 
   } 
}

Ответ 1

Как правило, вы всегда должны копаться в журналах, чтобы получить реальное исключение (по крайней мере, в Spark 1.3.1).

ТЛ, д-р
безопасная конфигурация для Spark под пряжей
spark.shuffle.memoryFraction=0.5 - это позволит использовать случайное использование большего количества выделенной памяти
spark.yarn.executor.memoryOverhead=1024 - это установлено в МБ. Yarn убивает исполнителей, когда их использование памяти больше (executor-memory + executor.memoryOverhead)

Немного больше информации

Из чтения вашего вопроса вы упоминаете, что вы получаете случайное исключение.

В случае org.apache.spark.shuffle.MetadataFetchFailedException: Missing an output location for shuffle вы должны увеличить spark.shuffle.memoryFraction, например, до 0,5

Самая распространенная причина, по которой Янь, убивающая моих исполнителей, была памятью, превышающей ожидаемую. Чтобы избежать увеличения spark.yarn.executor.memoryOverhead, я установил его на 1024, даже если мои исполнители используют только 2-3G памяти.

Ответ 2

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

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

  1. Установить количество исполнителей = 5
  2. Установить количество ядер executeotr = 4
  3. Установить накладные расходы памяти = 2G
  4. случайный раздел = 20 (чтобы использовать максимальный параллелизм на основе исполнителей и ядер)

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