Десять минут, чтобы полностью понять механизм управления памятью Spark.

Spark
Десять минут, чтобы полностью понять механизм управления памятью Spark.

Эта статья приняла участие в мероприятии «Церемония создания новичков», чтобы вместе начать путь создания золота.

Сегодня я познакомлю вас с моделью памяти Spark.Там много галантереи, не пропустите~

с частым размещением данныхMapreduceДвигатель другой, Спарк основан на内存Распределенный вычислительный движок со встроенным мощным механизмом управления памятью для обеспечения优先内存обработки и поддерживает хранение данных на диске.

В этой статье основное внимание будет уделено тому, как реализовано управление памятью Spark, а именно:

  • Обзор искровой памяти
  • Механизм управления памятью Spark
  • Выделение памяти в режиме Spark on Yarn

1 Обзор памяти Spark

Во-первых, краткое введение в основной процесс запуска Spark.

  • пользователь вDriverКлиент отправляет задачу и инициализирует рабочую среду (SparkContext и т. д.).
  • Драйвер в соответствии с конфигурациейResoureManagerПодать заявку на ресурсы (исполнители и ресурсы памяти)
  • Менеджер ресурсов ResoureManager выбирает соответствующийworkerNode создает процесс-исполнитель
  • ExecutorЗарегистрируйтесь у Водителя и дождитесь его назначенияtaskЗадача
  • Водительская сторона завершенаSparkContextИнициализируйте, создайте DAG, назначьте набор задач Executor для выполнения.
  • Исполнитель запускает поток для выполнения задачи задачи и возвращает результат.

Spark запустится при выполнении задачиDriverиExecutorдва процесса. Помимо того, что он служит узлом выполнения для задач отправки Spark, процесс Driver также отвечает за подачу заявок на ресурсы Executor, регистрацию Executors и отправку задач для завершения координации и планирования всей задачи. Процесс Executor отвечает за выполнение определенных задач на рабочих узлах.taskзадачу и поддерживать связь с драйвером, чтобы вернуть результат.

Как видно из вышеизложенного, расчет данных Spark происходит в основном вExecutorЗавершение в процессе и исполнитель для RDD持久化хранение иShuffleЗапущенный процесс осуществляется единообразно в рамках механизма управления памятью Spark, и запущенные в нем задачи также共享Память Executor, поэтому в этой статье в основном описывается управление памятью Executor.

Искровая память делится на堆内内存(память в куче) и堆外内存(память вне кучи). где память в куче основана наJVM内存модель, в то время как доступ к памяти вне кучи осуществляется путем вызова базовойJDK Unsafe API. Два типа памяти объединены интерфейсом модуля управления памятью Spark.

def acquireStorageMemory(...): Boolean  //申请存储内存
def acquireExecutionMemory(...): Long   //申请执行内存
def releaseStorageMemory(...): Unit     //释放执行内存
def releaseStorageMemory(...): Unit     //释放存储内存

1.1 Память в куче Spark

Исполнитель какJVMПроцесс, внутреннее устройство которого основано на модели управления памятью JVM.

Spark инкапсулирует унифицированный интерфейс управления памятью поверх него.MemoryManager, за счет разумного планирования (логического) пространства кучи JVM заполнить пространство памяти экземпляра объекта申请и释放. Убедитесь, что пространство памяти максимально увеличено в соответствии с операционным механизмом Spark.

участие здесьJVM堆Понятие пространства, простое описание есть в программе, о экземпляре объекта | массиве创建,使用и释放Вся память управляется и распределяется в области памяти, называемой «кучей JVM» в JVM.

После того, как программа Spark создаст объект, JVM сохранит его в куче памяти.分配определенный размер пространства, создатьClass对象И возвращает ссылку на объект, Spark сохраняет ссылку на объект и записывает информацию о занятой памяти.

Параметры памяти в куче в Spark:-executor-memoryили-spark-executor-memory. Обычно он определяется в параметрах при отправке задачи и совпадает с-executor-coresи другие связанные конфигурации передаются в ResourceManager для приложения ресурсов Executor.

Создайте определенное количество Executors на рабочем узле, и каждый Executor будет выделен-executor-memoryразмер оперативной памяти. Память в куче Executor совместно используется всеми задачами потока задач, и несколько потоков обмениваются данными в памяти.

Память кучи Spark в основном делится наStorage(память для хранения),Execution(исполнительная память) иOther(Другое) несколько частей.

  • Использование памяти для кэширования данных RDD и широковещательных переменных
  • Выполнение обеспечивает только использование памяти для процесса перемешивания
  • Другое предоставляет место в памяти для внутренних объектов Spark и пользовательских объектов.

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

1.2 Память Spark вне кучи

Spark1.6На основе памяти в куче вводится память вне кучи для дальнейшей оптимизации использования памяти Spark.

На самом деле, если у вас есть опыт программирования, связанный с Java, я думаю, вам не привыкать к использованию памяти вне кучи. его основной вызов基于CМетод класса JDK Unsafe через指针Непосредственно выполнять операции с памятью, включая применение, использование, удаление и освобождение памяти.

Spark отказался от предыдущей версии после 2.xTachyon, используя общий Java на основеJDK Unsafe APIдля управления памятью вне кучи. Этот режим не применяется к памяти в JVM, а напрямую управляет памятью операционной системы, уменьшая объем памяти в JVM.空间切换стоимость, уменьшаяGC回收Занято потребление, чтобы добиться точного контроля памяти.

Память вне кучи не включена по умолчанию, вам нужно установить ее в конфигурацииspark.memory.offHeap.enabledУстановите значение True и настройтеspark.memory.offHeap.sizeПараметр задает размер кучи.

Для разделения памяти вне кучи она включает только две области: Execution (память выполнения) и Storage (память для хранения), которые совместно используются всеми задачами потока задач.

2 Механизм управления памятью Spark

Как было сказано выше, соотношение областей памяти Spark in-heap и out-of-heap в разных режимах разное.

До Spark 1.6 Spark использовал静态管理(Менеджер статической памяти), соотношение распределения памяти выполнения и памяти хранения静态, значение которого является заданным системой параметром по умолчанию.

После Spark 1.6, чтобы учесть динамическую гибкость управления памятью, управление памятью Spark было изменено на统一管理(Unified Memory Manager), поддерживает память для хранения и выполнения动态占用. Поскольку статический метод управления все еще зарезервирован, вы можете пройтиspark.memory.useLegacyModeпараметр включен.

2.1 Менеджер статической памяти

Spark — это самый примитивный режим управления памятью.По умолчанию параметры конфигурации памяти, установленные системой, используются для выделения соответствующего пространства памяти, такого как Storage и Execution, и поддерживают пользовательскую модификацию конфигурации.

1. Выделение памяти в куче

Пространство кучи памяти в целом разделено наStorage(память для хранения),Execution(исполнительная память),Other(Другая память) три части, по умолчанию в соответствии с6:2:2отношение деления. Среди них параметры области памяти Storage:spark.storage.memoryFraction(по умолчанию 0,6), параметры области исполнительной памяти:spark.shuffle.memoryFraction(по умолчанию 0,2). Другая область памяти в основном используется для хранения определяемых пользователем структур данных и внутренних метаданных Spark, что составляет 20% системной памяти.

В области Storage memory 10% от размера используется какReservedЗарезервировать место для предотвращения переполнения памяти по параметрам:spark.shuffle.safetyFraction(по умолчанию 0,1) Управление. 90% пространства используется как доступная память для хранения.Вот область памяти, где Executor кэширует данные RDD и широковещательные данные.Параметры такие же, как Reserved. другая частьUnrollОбласть, в которой в основном хранятся данные процесса развертывания, занимает 20% доступного места для хранения.

Процесс развертывания:
Прежде чем RDD будет кэширован в памяти,partitionЭкземпляр объекта записи в другой области памяти в куче不连续хранится в космосе. В процессе кэширования RDD разделы в дискретном пространстве хранения преобразуются в连续存储空间Объект Block хранится в области памяти Storage, этот процесс называется Unroll.

В области Execution memory 20% размера используется как зарезервированное зарезервированное пространство для предотвращения OOM и других ситуаций, когда памяти не хватает, по параметрам:spark.shuffle.safetyFraction(по умолчанию 0,2) Контроль. 80% пространства используется как доступная память выполнения для кэширования промежуточных данных процесса тасования.Параметры:spark.shuffle.safetyFraction(по умолчанию 0,8).

Формула расчета

可用的存储内存 = 
      systemMaxMemory 
      * spark.storage.memoryFraction
      * spark.storage.safetyFraction
可用的执行内存 =
     systemMaxMemory 
     * spark.shuffle.memoryFraction 
     * spark.shuffle.safetyFraction

2. Память вне кучи

По сравнению с памятью в куче выделение памяти вне кучи проще. Память вне кучи по умолчанию384M, по системному параметруspark.yarn.executor.memoryOverheadнастраивать. Общая память делится на две части: Storage и Execution.Распределение этой части соответствует памяти в куче.Параметры:spark.memory.storageFactionПринять решение. В памяти вне кучи обычно хранятся сериализованные двоичные данные (поток байтов), которые представляют собой непрерывную область памяти в пространстве для хранения, и ее размер можно точно рассчитать, поэтому в настоящее время нет необходимости устанавливать зарезервированное пространство.

3. Резюме

  • Механизм реализации прост и понятен
  • Склонна к возникновению проблема дисбаланса памяти, то есть на одной стороне Storage and Execution имеется избыточная память, а на другой — недостаточное содержимое.
  • От разработчиков требуется полное понимание механизма хранения, а настройка неудобна

Для более подробных обсуждений добро пожаловать в мой личный WeChat:youlong525

2.2 Единый диспетчер памяти

Чтобы решить (Менеджер статической памяти) управление статической памятью内存失衡д., Spark использует новый режим управления памятью после 1.6 — Unified Memory Manager (Унифицированный диспетчер памяти). В новом режиме убрано и включено статическое выделение памяти Executor в старом режиме内存动态占比机制и разделить Storage и Execution на единую общую область памяти.

1. Память в куче

Куча памяти делится в целом наUsable Memory(доступная память) иReversed Memory(зарезервированная память) две части. Зарезервированная память используется в качестве области использования памяти для нештатных ситуаций, таких как OOM, и по умолчанию выделяется 300 МБ. Доступная память может быть дополнительно разделена на объединенную память (Единая память) и две другие части Прочей памяти, соотношение по умолчанию — 6:4.

Storage (память хранения), Execution (память выполнения) и Other memory в объединенной памяти имеют те же параметры и область применения, что и режим статической памяти, и здесь повторяться не будут. В настоящее время он включен только между Storage и Execution.动态内存占用механизм.

Механизм динамического заполнения памяти

  1. Установите начальное значение памяти, то есть и Исполнение, и Хранилище должны установить свои диапазоны областей памяти (параметр по умолчанию 0,5)
  2. Если на одной стороне недостаточно памяти, а на другой стороне есть свободная память, она может занять пространство памяти другой стороны.
  3. Когда памяти обеих сторон недостаточно, диск нужно поставить на обработку.
  4. Когда исполнительная память занята, Storage необходимо сбросить эту часть на жесткий диск и вернуть место
  5. Когда память Storage занята, Execution не нужно возвращать

2. Память вне кучи

В соответствии с распределением в режиме статического управления значение по умолчанию для памяти вне кучи составляет 384 МБ. Целое разделено на две части, Storage и Execution, и включено动态内存占用механизм, в котором коэффициент инициализации по умолчанию равен 0,5.

Формула расчета

// 可用的存储&执行内存 = 
   (systemMaxMemory -ReservedMemory) 
    * spark.memoryFraction 
    * spark.storage.storageFraction
// (启用内存动态分配机制,己方内存不足时可占用对方)

3. Резюме

  • Динамическое соотношение памяти для улучшения разумного использования памяти
  • Унифицированное управление памятью для хранения и выполнения для легкой настройки и обслуживания
  • Поскольку выполнение занимает память Storage, планировать его не нужно, и возникает ситуация, когда память Storage недостаточно часто проверяется GCed.

3 Распределение памяти в режиме Spark On Yarn

Благодаря надежному механизму управления памятью Spark Executor может эффективно обрабатывать операции с памятью и потоки данных RDD в узлах. Yarn, как менеджер ресурсов для выделения памяти Executor, как обеспечить наиболее рациональное выделение памяти в процессе — тоже проблема, достойная внимания.

Сначала посмотрите на основной процесс Spark On Yarn:

    1. Spark DriverОтправьте программу и подайте заявку на Yarn for Application
    1. Yarn принимает ответ на запрос и создает AppMaster на узле NodeManager.
    1. AppMasterПодать заявку на ресурсы (контейнер) из Yarn ResourceManager
    1. Выберите соответствующий узел для созданияContainer(исполнительный процесс)
    1. Последующие водители начинают планировать и запускать задачи

Режимы Yarn Client и Yarn Cluster различаются в некоторых аспектах, но основные процессы схожи. Конфигурация памяти, задействованная во всем процессе, следующая (конфигурация исходного кода по умолчанию):

var executorMemory = 1024                    
val MEMORY_OVERHEAD_FACTOR = 0.10   
val MEMORY_OVERHEAD_MIN = 384   

// Executo堆外内存
val executorMemoryOverhead = 
    sparkConf.getInt("spark.yarn.executor
    .memoryOverhead",
    math.max((MEMORY_OVERHEAD_FACTOR
       * executorMemory).toInt
       , MEMORY_OVERHEAD_MIN))

// Executor总分配内存
val executorMem= args.executorMemory
       + executorMemoryOverhead 

Итак, предположим, что когда мы отправляем искровую программу, если мы устанавливаем-executor-memory=5г.

spark-submit 
  --master yarn-cluster 
  --name test 
  --executor-memory 5g 
  --driver-memory 5g

По формуле расчета в исходном коде мы можем получить:

memoryMem= args.executorMemory(5120) + executorMemoryOverhead(512) = 5632M

Однако на самом делеYarn UIПамять не это значение? Это связано с тем, что Yarn включен по умолчанию.资源规整化.

1. Регулировка ресурсов пряжи

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

  • определение

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

 公式: ceil(a/b)*b 
(a是程序申请资源,b为规整化因子)
  • Связанная конфигурация
  yarn.scheduler.minimum-allocation-mb:
   最小可申请内存量,默认是1024
  yarn.scheduler.minimum-allocation-vcores:
   最小可申请CPU数,默认是1
  yarn.scheduler.maximum-allocation-mb:
   最大可申请内存量,默认是8096
  yarn.scheduler.maximum-allocation-vcores:
   最大可申请CPU数,默认是4

Вернемся к предыдущему расчету памяти: поскольку вычисленное значение memoryMem равно5632, не является целым числом, кратным коэффициенту нормализации (1024), поэтому его необходимо пересчитать:

memoryMem = ceil(5632/1024)*1024=6144M

2. Разница в распределении памяти драйвера в режиме Yarn

Yarn Client и Cluster отправляются двумя способами, и выделение памяти Executor и Driver также отличается. Все ApplicationMasters в Yarn позволяютContainerбежать;

По умолчанию Контейнер в клиентском режиме имеет1GПамять, 1 ядро ​​процессора, конфигурация режима кластера задаетсяdriver-memoryиdriver-cpuЧтобы указать, то есть драйвер в режиме клиента является значением памяти по умолчанию, драйвер в режиме кластера является пользовательской конфигурацией.

  1. Кластерный режим (память драйвера: 5g): ceil(a/b)*b может получить память драйвера 6144M
  2. клиентский режим (память драйвера: 5g): ceil(a/b)*b может получить память драйвера 5120M

3. Резюме

В качестве диспетчера распределенных ресурсов Apache Yarn имеет собственный механизм оптимизации управления памятью. При развертывании программ Spark в Yarn вам необходимо учитывать механизмы обработки памяти обоих, что является одним из наиболее часто упускаемых из виду знаний в производственных приложениях.

напиши в конце

Механизм управления памятью Spark является ключевым содержанием принципа и настройки Spark.Эта статья начинается с двух режимов, Static Memory Manager (статический режим управления) и Unified Memory Manager (унифицированный режим управления), и простыми словами объясняет, как работает вычислительная модель Spark. управление памятью.В конце описывается выделение памяти в Spark On Yarn.Надеюсь вышеизложенное может вам помочь.

》》》Чтобы получить больше хороших статей, пожалуйста, обратите внимание на мой публичный аккаунт: Big Data Arsenal