【Spark】RDD依赖关系

683 阅读2分钟

这是我参与11月更文挑战的第14天,活动详情查看:2021最后一次更文挑战

一、概述

RDD 只支持粗粒度转换, 即在大量记录上执行的单个操作。将创建 RDD 的一系列 Lineage (血统)记录下来, 以便恢复丢失的分区。

RDDLineage 会记录 RDD 的元数据信息和转换行为, 当该 RDD 的部分分区数据丢失时, 可根据这些信息来重新运算和恢复丢失的数据分区。

如图: 2021-02-2016-18-25.png

RDD 和 它依赖的 父RDD(s) 的关系有两种不同的类型, 即窄依赖( narrow dependency) 和 宽依赖(wide dependency)。

依赖有2个作用:

  1. 用来解决数据容错
  2. 用来划分 stage

窄依赖: 1:1n:1 宽依赖: n:m; 意味着有 shuffle

窄依赖和宽依赖如图: 2021-02-2016-20-57.png

DAG (Directed Acyclic Graph) 有向无环图。原始的 RDD 通过一系列的转换就就形成了 DAG, 根据 RDD 之间的依赖关系的不同将 DAG 划分成不同的 Stage:

  • 对于窄依赖, partition 的转换处理在 Stage 中完成计算
  • 对于宽依赖, 由于有 Shuffle 的存在, 只能在 parent RDD 处理完成后, 才能开始接下来的计算,宽依赖是划分 Stage 的依据

RDD 任务切分中间分为: Driver programeJobStage(TaskSet)Task

  • Driver program : 初始化一个 SparkContext 即生成一个 Spark 应用
  • Job : 一个 Action 算子就会生成一个 Job
  • Stage : 根据 RDD 之间的依赖关系的不同将 Job 划分成不同的 Stage, 遇到一个宽依赖则划分一个 Stage
  • Task : Stage 是一个 TaskSet, 将 Stage 划分的结果发送到不同的 Executor 执行即为一个 Task
  • TaskSpark 中任务调度的最小单位; 每个 Stage 包含许多 Task, 这些 Task 执行的计算逻辑相同的, 计算的数据是不同的

注意: Driver programe -> Job -> Stage -> Task 每一层都是 1对n 的关系。

// 窄依赖
val rdd1 = sc.parallelize(1 to 10, 1)
val rdd2 = sc.parallelize(11 to 20, 1)
val rdd3 = rdd1.union(rdd2)
rdd3.dependencies.size
rdd3.dependencies

// 打印rdd1的数据
rdd3.dependencies(0).rdd.collect

// 打印rdd2的数据
rdd3.dependencies(1).rdd.collect


// 宽依赖
val random = new scala.util.Random
val arr = (1 to 100).map(idx => random.nextInt(100))
val rdd1 = sc.makeRDD(arr).map((_, 1))
val rdd2 = rdd1.reduceByKey(_+_)

// 观察依赖
rdd2.dependencies
rdd2.dependencies(0).rdd.collect
rdd2.dependencies(0).rdd.dependencies(0).rdd.collect

二、案例:WordCount

val rdd1 = sc.textFile("/wcinput/wc.txt")
val rdd2 = rdd1.flatMap(_.split("\\s+"))
val rdd3 = rdd2.map((_, 1))
val rdd4 = rdd3.reduceByKey(_+_)
val rdd5 = rdd4.sortByKey()
rdd5.count

// 查看RDD的血缘关系
rdd1.toDebugString
rdd5.toDebugString


// 查看依赖
rdd1.dependencies
rdd1.dependencies(0).rdd
rdd5.dependencies
rdd5.dependencies(0).rdd


// 查看最佳优先位置
val hadoopRDD = rdd1.dependencies(0).rdd
hadoopRDD.preferredLocations(hadoopRDD.partitions(0))


# 使用 hdfs 命令检查文件情况
hdfs fsck /wcinput/wc.txt -files -blocks -locations