一、Spark与Hadoop的关系
Spark和Hadoop只是共用了底层的MapReduce编程模型,即它们均是基于MapReduce思想所开发的分布式数据处理系统。
Hadoop采用MapReduce和HDFS技术,其MapReduce计算模型核心即Map操作和Reduce操作,在这个计算模型的工作流程中还存在一些可以由用户自定义的Partition和Combine等操作;HDFS则是对Hadoop的输入文件、Map产生的结果文件、Shuffle产生的结果文件等等的一个文件管理系统,其IO操作都是基于磁盘的。Hive、HBase、Pig、Mathout和ZooKepper等都是基于Hadoop开发的系统。
Hadoop处理的数据量本身很大时,经过N个Map操作会被划分为多个数据块,一般这些块都需要经过merg操作存放到磁盘中,IO量是很大的,尤其是小文件(文件大小要小于系统处理的block时)数量过多时,不仅IO操作增多而且还会拖累网络的流量负载。众所周知,对于迭代计算,Hadoop只能是鞭长莫及,因为许多处理的中间文件都被放置在磁盘中,要利用这些中间文件进行迭代计算对系统性能来说是不现实的。Hadoop本身的容错机制即冗余副本,占据了很多资源,当然,Hadoop2已经开始使用log的方法来强化容错机制。
Spark对计算模型进行了细化,MapReduce的计算模型被分为transformations操作和actions操作,transformations操作包含了map、reduceByKey、union和join等许多对数据集RDD进行转换的操作,而actions则提供了对数据集中的数据操作的接口。数据集RDD是基于内存的,甚至可以将一个RDD视为一个静态变量类型,这样进行迭代计算就成为了可能,而且减少了磁盘IO操作。
二、粗粒度与细粒度的共享内存模式
粗粒度的寻址模式相比细粒度的寻址模式,可以寻址的最小页的大小要大一些。这一点被Spark运用得非常灵活。
首先,粗粒度寻址是RDDs所采取的寻址方式。尽管页面相比细粒度下比较大,但是由于许多应用都是执行相同的迭代操作,所以并不影响系统性能。粗粒度寻址来共享内存也是RDDs划分的重要依据,否者页面太小,导致数据集容量有限,对计算性能是不利的。
其次,RDDs支持不同方式的寻址。RDDs在写操作时采用粗粒度寻址,而读方式下却可以采取粗粒度或者细粒度的寻址方式。同时,在进行故障恢复时,RDDs会通过细粒度方式寻址及lineage的低开销来实现。
三、RDDs与Spark
RDDs的运用成就了Spark。Spark的工作单位是数据集RDDs,而对RDD的操作实际上是对其内部的Partitions的操作。
RDDs之间的关系分为两类:narrow dependencies和wide dependencies,前者是指RDD的工作分区只允许一个child RDD共享,而后者则指RDD的工作分区允许多个child RDD共享。一般来说,map操作产生的都是narrow dependencies的RDD,而join操作产生的都是wide dependencies的RDD,总之不同的操作依靠其特性会产生不同的依赖关系。narrow dependencies的RDD由于资源利用呈流式,所以适合于以管道形式来并行执行操作。
Spark在RDDs上执行任务时,RDDs是由parent RDD创建的,这个parent RDD即目标RDD,其所创建的RDD负责执行副本任务。执行阶段:首先,每个阶段都会尽可能多的安排一些narrow dependencies的transformations操作;然后,每个阶段相互交接的时间段即shuffle阶段,这一阶段需要wide dependencies的操作或者一部分Partitions已经执行完并且能够减缓parent RDD计算压力的RDD;最后,就是对执行失败的RDDs进行恢复重新执行,直到目标RDD(parent RDD)执行完成。
transformations操作包括:
1、map操作。map操作返回一个RDD,操作对象与parent RDD具有相同的分区表和优先级,可以返回parent RDD迭代计算所需的值。
2、union操作。union操作返回一个RDD,操作对象为两个RDD,将这两个RDD的Partitions进行合并操作。
3、simple操作。
4、join操作。join操作可能产生narrow dependencies、wide dependencies或者混合的RDDs。当join的对象RDDs都具有相同的Partition函数时,产生narrow dependencies的RDDs;当RDDs的Partition函数不同时,产生wide dependencies;一个有Partition函数而一个没有时,产生混合RDDs。无论哪种情况,结果RDD都含有一个继承的或者默认的Partition函数。
5、reduceByKey操作。
action操作包括:
1、count操作。对RDD的长度计数。
2、collect操作。获取RDD中的一列数据。
3、reduce操作。将RDD数据集中的数据返回给用户。
此外,采用<K,V>的计算模式,Spark和RDDs交互是通过language-intergrated API接口实现的。
四、RDDs的容错机制
容错机制是RDDs需要重点考虑的因素。首先,RDDs是不能容忍调度错误的。其次,数据的恢复速度是关乎系统性能的重要因素。
RDD的创建由用户或者RDD执行,而Spark的驱动程序会将RDD从Parent RDD的创建到执行的各个阶段的每一步都记录在lineage中,所以,如果这个RDD任务失败时,Spark会根据相应的lineage在本地或者其他节点上恢复该RDD。上述容错机制需要lineage的记录,而lineage的方法只对narrow dependencies具有良好的效果,对于wide dependencies则效果欠佳。wide dependencies的容错方法一般推荐checkpoint机制。