通过WordCount详解过程图,观察Spark的运行过程,思考RDD操作类型有几种?有了初步的思考,下文会给出RDD操作类型区别和实战演示
Q1:RDD 的操作有几种 ? (想了解更多Spark持久化操作请点击: Spark cache和persist使用场景和区别)
有如下三种:
(1)transformation:进行数据状态的转换,对已有的RDD创建新的RDD。
(2)Action:触发具体的作业,对RDD最后取结果的一种操作
(3)Controller:对性能效率和容错方面的支持。persist , cache, checkpoint
1. Transformation:进行数据状态的转换,对已有的RDD创建新的RDD。
例如:(1)map(func) :返回一个新的分布式数据集,由每个原元素经过func函数转换后组成
(2)filter(func) : 返回一个新的数据集,由经过func函数后返回值为true的原元素组成
(3)flatMap(func) : 类似于map,但是每一个输入元素,会被映射为0到多个输出元素(因此,func函数的返回值是一个Seq,而不是单一元素)
(4)sample(withReplacement, frac, seed) : 根据给定的随机种子seed,随机抽样出数量为frac的数据
(5)union(otherDataset) : 返回一个新的数据集,由原数据集和参数联合而成
(6)groupByKey([numTasks]) : 在一个由(K,V)对组成的数据集上调用,返回一个(K,Seq[V])对的数据集。注意:默认情况下,使用8个并行任务进行分组,你可以传入numTask可选参数,根据数据量设置不同数目的Task
(7)reduceByKey(func, [numTasks]) : 在一个(K,V)对的数据集上使用,返回一个(K,V)对的数据集,key相同的值,都被使用指定的reduce函数聚合到一起。和groupbykey类似,任务的个数是可以通过第二个可选参数来配置的。
(8)join(otherDataset, [numTasks]) : 在类型为(K,V)和(K,W)类型的数据集上调用,返回一个(K,(V,W))对,每个key中的所有元素都在一起的数据集
(9)groupWith(otherDataset, [numTasks]) : 在类型为(K,V)和(K,W)类型的数据集上调用,返回一个数据集,组成元素为(K, Seq[V], Seq[W]) Tuples。这个操作在其它框架,称为CoGroup
(10)cartesian(otherDataset) : 笛卡尔积。但在数据集T和U上调用时,返回一个(T,U)对的数据集,所有元素交互进行笛卡尔积。
2. Action:触发具体的作业,对RDD最后取结果的一种操作。
例如:(1)reduce(func):通过函数func先聚集各分区的数据集,再聚集分区之间的数据,func接收两个参数,返回一个新值,新值再做为参数继续传递给函数func,直到最后一个元素
(2)collect():以数据的形式返回数据集中的所有元素给Driver程序,为防止Driver程序内存溢出,一般要控制返回的数据集大小
(3)count():返回数据集元素个数
(4)first():返回数据集的第一个元素
(5)take(n):以数组的形式返回数据集上的前n个元素
(6)top(n):按默认或者指定的排序规则返回前n个元素,默认按降序输出
(7)takeOrdered(n,[ordering]): 按自然顺序或者指定的排序规则返回前n个元素
(8)saveAsTextFile()
Spark action级别的操作,特点是内部都调用runJob方法,常用的action:reduce(1+2+3+4—-》1+2=3+3=6+4=10),aggregate,collection(把所有的结果放在driver上),count执行结果有多少条,take获取执行结果的某几条,saveAsTextFile把执行结果保存在Hadoop支持的文件系统上,foreach循环每一条元素;countByKey:可看一个key有多少个value;
注意:reduceByKey不是action,它是一个transformation
action级别操作举例:
val numbers = sc.parallelize(1 to 100)
scala> numbers.reduce(_+_) 触发作业
val result = numbers.map(2*_)
scala> result.collect
源代码:
/**
*Return an array that contains all of the elements in this RDD.
*/
defcollect(): Array[T] = withScope {
valresults = sc.runJob(this, (iter: Iterator[T]) => iter.toArray)
Array.concat(results: _*)
}
Driver会收集每个task的执行结果,每个Executor上会有很多的task。(通过网络通信传输收集)
如果想在命令终端上看到执行结果就必须collect
凡是Action的级别的操作都会触发sc.runJob。言外之意:一个应用程序会有很多的job。
scala> result.count()
def count(): Long = sc.runJob(this,Utils.getIteratorSize _).sum
scala> val topN = numbers.take(5)
countByKey:可看一个key有多少value
scala> val scores =Array(Tuple2(1,100),Tuple2(2,89),Tuple2(2, 99), Tuple2(3, 88))
scores: Array[(Int, Int)] = Array((1,100),(2,89), (2,99), (3,88))
scala> val scoresRDD =sc.parallelize(scores)
scoresRDD: org.apache.spark.rdd.RDD[(Int,Int)] = ParallelCollectionRDD[1] at parallelize at <console>:29
defcountByKey(): Map[K, Long] = self.withScope {
self.mapValues(_ => 1L).reduceByKey(_ + _).collect().toMap
}
3. Controller:对性能效率和容错方面的支持。persist , cache, checkpoint
Q2:假定input/*下面有10个小于128M的文件,这个过程产生几个Partition?12个
Q2:并行度,Shuffle,Partition之间的关系?
并行度和Shuffle没有任何关系,并行度是涉及到执行效率的,Shuffle由RDD的依赖关系决定,如上如果不指定并行度,并行度会传递过去的。设置多少个并行度就有多少个Partition。
想了解更多Spark持久化操作请点击: Spark cache和persist使用场景和区别