RDD (Resilient Distributed Dataset) — устойчивый распределенный набор данных. Это самая базовая и важная модель данных в Spark. Он состоит из разделов, и каждый раздел обрабатывается подчиненным узлом Spark Worker, тем самым поддерживая распределенные параллельные вычисления. RDD обеспечивает автоматическую отказоустойчивость посредством контрольных точек, а также имеет функции планирования и масштабирования с учетом местоположения. RDD также предоставляет механизм кэширования, который может значительно повысить скорость обработки данных.
Видеообъяснение следующее:
В примере WordCount каждый шаг генерирует новый RDD для сохранения результатов этого шага. Вы также можете создать RDD следующим образом:
scala> val myrdd = sc.parallelize(Array(1,2,3,4,5,6,7,8),2)
Эта строка кода создает коллекцию RDD с именем myrdd, которая содержит массив, и этот RDD состоит из двух разделов. Вы можете проверить длину разделов, просмотрев оператор разделов RDD.
scala> myrdd.partitions.length
res0: Int = 2
Какова же связь между RDD, разделом и рабочим узлом? Здесь мы возьмем только что созданный myrdd в качестве примера, чтобы проиллюстрировать взаимосвязь между ними, как показано на рисунке ниже.
На рисунке предполагается, что имеется два рабочих подчиненных узла. myrdd содержит два раздела, каждый раздел будет иметь номер раздела, а номер раздела начинается с нуля. На рисунке 9.9 мы видим, что данные в разделе 0 обрабатываются на первом Worker, то есть: {1,2,3,4}, а данные в разделе 1 обрабатываются на втором Worker, то есть: {; 5,6,7,8}.
Совет: Под разделом можно понимать физическое понятие, а данные в нем обрабатываются задачами, выполняемыми Исполнителем на Worker. Крайний пунктирный прямоугольник представляет собой RDD. Видно, что на самом деле это логическая концепция.
После понимания базовой концепции RDD, какими характеристиками обладает RDD? Исходный код Spark RDD объясняет характеристики RDD следующим образом.
* Internally, each RDD is characterized by five main properties:
*
* - A list of partitions
* - A function for computing each split
* - A list of dependencies on other RDDs
* - Optionally, a Partitioner for key-value RDDs (e.g. to say that the RDD is hash-partitioned)
* - Optionally, a list of preferred locations to compute each split on (e.g. block locations for an HDFS file)
Из этого комментария вы можете понять, что RDD имеет следующие пять основных характеристик:
Для RDD каждый раздел будет обрабатываться вычислительной задачей и определяет степень детализации параллельных вычислений. Пользователи могут указать количество сегментов RDD при создании RDD. Если не указано, будет использоваться значение по умолчанию. Значением по умолчанию является количество ядер ЦП, выделенных программе.
Расчет RDD в Spark основан на разделах. Каждый RDD должен реализовать функцию вычисления для достижения цели обработки данных.
Программный код WordCount можно дизассемблировать и выполнить за один шаг. Во время каждого преобразования можно определить новый RDD для сохранения результатов этого шага, как показано ниже.
scala> val rdd1 = sc.textFile("hdfs://bigdata111:9000/input/data.txt")
scala> val rdd2 = rdd1.flatMap(_.split(" "))
scala> val rdd3 = rdd2.map((_,1))
scala> val rdd4 = rdd3.reduceByKey(_+_)
scala> rdd4.saveAsTextFile("hdfs://bigdata111:9000/output/spark/wc")
Всего здесь определены 4 RDD, а именно: rdd1, rdd2, rdd3 и rdd4, среди которых: rdd4 зависит от rdd3, rdd3 зависит от rdd2 и rdd2 зависит от rdd1. По различным зависимостям этапы выполнения задачи могут быть разделены для поддержки механизма отказоустойчивости контрольных точек.
Совет: Если данные определенного раздела теряются во время расчета, Spark может выполнить пересчет с помощью этой зависимости вместо пересчета всех разделов RDD.
Partitioner — это функция разделения Spark RDD. Внутри Spark реализованы два типа функций секционирования: один — HashPartitioner, основанный на алгоритме хеширования, другой — RangePartitioner, основанный на диапазоне; Пользовательские функции разделов также могут быть реализованы путем наследования Partitioner. Функция разделения не только определяет количество разделов в самом RDD, но также определяет количество разделов в выводе RDD Shuffle.
На основе информации в этом списке Spark будет распределять вычислительные задачи как можно больше по местам хранения блоков данных, которые ему необходимо обработать при планировании задач, что может повысить эффективность обработки данных.