Spark是加州大学伯克利分校的AMP实验室开源的类似MapReduce的通用并行计算框架,拥有MapReduce所具备的分布式计算的优点。但不同于MapReduce 的是,Spark更多地采用内存计算,减少了磁盘读写,比MapReduce性能更高。同时,它提供了更加丰富的函数库,能更好地适用于数据挖掘与机器学习等分析算法。
Spark在Hadoop生态圈中主要是替代MapReduce进行分布式计算,如下图所示。同时,组件SparkSQL可以替换Hive对数据仓库的处理,组件Spark Streaming可以替换Storm对流式计算的处理,组件Spark ML可以替换Mahout数据挖掘算法库。
Spark在Hadoop生态圈中的位置
01
Spark的运行原理
如今,我们已经不再需要去学习烦琐的MapReduce设计开发了,而是直接上手学习Spark的开发。这一方面是因为Spark的运行效率比MapReduce高,另一方面是因为Spark有丰富的函数库,开发效率也比MapReduce高。
首先,从运行效率来看,Spark的运行速度是Hadoop的数百倍。为什么会有如此大的差异呢?关键在于它
们的运行原理,Hadoop总要读取磁盘,而Spark更多地是在进行内存计算,如下图所示。
Hadoop的运行总是在读写磁盘
前面谈到,MapReduce的主要运算过程,实际上就是循环往复地执行Map与Reduce的过程。但是,在执行每一个Map或Reduce过程时,都要先读取磁盘中的数据,然后执行运算,最后将执行的结果数据写入磁盘。因此,MapReduce的执行过程,实际上就是读数据、执行Map、写数据、再读数据、执行Reduce、再写数据的往复过程。这样的设计虽然可以在海量数据中减少对内存的占用,但频繁地读写磁盘将耗费大量时间,影响运行效率。
相反,Spark的执行过程只有第一次需要从磁盘中读数据,然后就可以执行一系列操作。这一系列操作也是类似Map或Reduce的操作,然而在每次执行前都是从内存中读取数据、执行运算、将执行的结果数据写入内存的往复过程,直到最后一个操作执行完才写入磁盘。这样整个执行的过程中都是对内存的读写,虽然会大量占用内存资源,然而运行效率将大大提升。
Spark框架的运行原理如下图所示,Spark在集部署时,在NameNode节点上部署了一个Spark Driver,然后在每个DataNode节点上部署一个Executor。Spark Driver是接收并调度任务的组件,而Executor则是分布式执行数据处理的组件。同时,在每一次执行数据处理任务之前,数据文件已经通过HDFS分布式存储在各个DataNode节点上了。因此,在每个节点上的Executor会首先通过Reader读取本
地磁盘的数据,然后执行一系列的Transformation操作。每个Transformation操作的输入是数据集,在Spark 中将其组织成弹性分布式数据集(RDD),从内存中读取,最后的输出也是RDD,并将其写入内存中。这样,整个一系列的Transformation操作都是在内存中读写,直到最后一个操作Action,然后通过Writer将其写入磁盘。这就是Spark的运行原理。
Spark框架的运行原理图
同时,Spark拥有一个非常丰富的函数库,许多常用的操作都不需要开发人员自己编写,直接调用函数库就可以了。这样大大提高了软件开发的效率,只用写更少的代码就能执行更加复杂的处理过程。在这些丰富的函数库中,Spark将其分为两种类型:转换(Transfer)与动作(Action)。
Transfer的输入是RDD,输出也是RDD,因此它实际上是对数据进行的各种Trans-formation操作,是Spark要编写的主要程序。同时,RDD也分为两种类型:普通RDD与名-值对RDD。
普通RDD,就是由一条一条的记录组成的数据集,从原始文件中读取出来的数据通常都是这种形式,操作普通RDD最主要的函数包括map、flatMap、filter、distinct、union、intersection、subtract、cartesian等。
名-值对RDD,就是k-v存储的数据集,map操作就是将普通RDD的数据转换为名-值对RDD。有了名-值对RDD,才能对其进行各种reduceByKey、
joinByKey等复杂的操作。操作名-值对RDD最主要的函数包括reduceByKey、groupByKey、combineByKey、mapValues、flatMapValues、keys、values、sortByKey、subtractByKey、join、leftOuterJoin、rightOuterJoin、cogroup等。
所有Transfer函数的另外一个重要特征就是,它们在处理RDD数据时都不会立即执行,而是延迟到下一个Action再执行。这样的执行效果就是,当所有一系列操作都定义好以后,一次性执行完成,然后立即写磁盘。这样在执行过程中就减少了等待时间,进而减少了对内存的占用时间。
Spark的另外一种类型的函数就是Action,它们输入的是RDD,输出的是一个数据结果,通常拿到这个数据结果就要写磁盘了。根据RDD的不同,Action 也分为两种:针对普通RDD的操作,包括collect、count、countByValue、take、top、reduce、fold、aggregate、foreach等;针对名-值对RDD的操作,包括countByKey、collectAsMap、lookup等。
02
Spark的设计开发
Spark的设计开发支持3种语言,Scala、Python与Java,其中Scala是它的原生语言。Spark是在Scala语言中实现的,它将Scala作为其应用程序框架,能够与Scala紧密集成。Scala语言是一种类似Java的
函数式编程语言,它在运行时也使用Java虚拟机,可以与Java语言无缝结合、相互调用。同时,由于Scala语言采用了当前比较流行的函数式编程风格,所以代码更加精简,编程效率更高。
并行计算框架前面讲解的那段计算词频的代码如下:
1val textFile = sc.textFile("hdfs://...")
2val counts = textFile.flatMap(line => line.split(""))
3 .map(word => (word, 1))
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论