1、窄依赖和宽依赖
- Narrow: 窄依赖:一个父RDD的partition只能被子RDD的某个partition使用一次
- Wide(shuffle):宽依赖是有shuffle的: 一个父RDD的partition被子RDD的partition使用多次
- 特列:join,如果父RDD的partion被子RDD的partion只使用了一次,就是窄依赖
- 对于窄依赖,Spark是以pipeline方式运行的,一条水管走到头。
-
当RDD分区丢失时(某个节点故障),spark会对数据进行重算。
对于窄依赖,由于父RDD的一个分区只对应一个子RDD分区,这样只需要重算和子RDD分区对应的父RDD分区即可,所以这个重算对数据的利用率是100%的;
对于宽依赖,重算的父RDD分区对应多个子RDD分区,这样实际上父RDD 中只有一部分的数据是被用于恢复这个丢失的子RDD分区的,另一部分对应子RDD的其它未丢失分区,这就造成了多余的计算;更一般的,宽依赖中子RDD分区通常来自多个父RDD分区,极端情况下,所有的父RDD分区都要进行重新计算。
如下图所示,b1分区丢失,则需要重新计算a1,a2和a3,这就产生了冗余计算(a1,a2,a3中对应b2的数据)。
-
遇到shuffle,拆stage
action ==> 产生Job ==> shuffle,拆成n stage ==> n task
一个stage的并行度由stage的最后一个rdd的分区决定。
2、Key-Value Pairs
官网:Working with Key-Value Pairs
http://spark.apache.org/docs/latest/rdd-programming-guide.html#working-with-key-value-pairs
-
While most Spark operations work on RDDs containing any type of objects, a few special operations are only available on RDDs of key-value pairs. The most common ones are distributed “shuffle” operations, such as grouping or aggregating the elements by a key.
虽然大多数Spark操作都在包含任何类型对象的RDDs上工作,但是只有少数特殊的操作只能在键值对的RDDs上使用。最常见的是分布式“shuffle”操作,例如按键grouping 或者 aggregating 元素。 -
In Scala, these operations are automatically available on RDDs containing Tuple2 objects (the built-in tuples in the language, created by simply writing (a, b)). The key-value pair operations are available in the PairRDDFunctions class, which automatically wraps around an RDD of tuples.
在Scala中,这些操作在包含Tuple2对象的RDDs上自动可用(该语言中内置的元组,只需编写(a, b)即可创建)。键值对操作在PairRDDFunctions类中是可用的,该类自动封装元组的RDD。
val lines = sc.textFile("data.txt")
val pairs = lines.map(s => (s, 1))
val counts = pairs.reduceByKey((a, b) => a + b)
比如点击reduceByKey查看源码,可以看到这个算子是属于PairRDDFunctions.scala类下的,那为什么我在使用的时候没有用到这个类呢,因为内部做了隐式转换的
打开RDD.scala源码,拉到最后,可以看到