Hadoop和Spark都是目前支流的大数据框架,然而随着Spark在速度和易用性方面体现出的劣势,一些国内外专家逐步推崇Spark技术,并且认为Spark才是大数据的将来。本文将会浅析Hadoop生态的倒退历程及其中局部组件的技术原理,最终就Hadoop是否会被Spark取代给出论断。
一、Hadoop的外围组件
在对Hadoop外围组件进行介绍之前,咱们须要先理解Hadoop解决了什么问题。Hadoop次要就是解决了大数据(大到一台计算机无法进行存储,一台计算机无法在要求的工夫内进行解决)的牢靠存储和解决。
Hadoop的外围组件次要有三个,别离是:HDFS、YARN和MapReduce。HDFS是是google三大论文之一的GFS的开源实现,是一个高度容错性的零碎,适宜部署在便宜的机器上的,适宜存储海量数据的分布式文件系统。而YARN是Hadoop的资源管理器,能够视为一个分布式的操作系统平台。相比于HDFS和YARN,MapReduce能够说是Hadoop的外围组件,以下会就MapReduce进行重点探讨。
MapReduce,通过简略的Mapper和Reducer的形象提供一个编程模型,能够在一个由几十台上百台的PC组成的不牢靠集群上并发地,分布式地解决大量的数据集,而把并发、分布式(如机器间通信)和故障复原等计算细节暗藏起来。而Mapper和Reducer的形象,又是各种各样的简单数据处理都能够合成为的根本元素。这样,简单的数据处理能够合成为由多个Job(蕴含一个Mapper和一个Reducer)组成的有向无环图(DAG),而后每个Mapper和Reducer放到Hadoop集群上执行,就能够得出后果。
在MapReduce中,Shuffle是一个十分重要的过程,正是有了看不见的Shuffle过程,才能够使在MapReduce之上写数据处理的开发者齐全感知不到分布式和并发的存在。
狭义的Shuffle是指图中在Map和Reuce之间的一系列过程。
二、Hadoop的局限和改良
只管Hadoop提供了解决海量数据的能力,然而Hadoop的外围组件——MapReduce的应用问题还是始终困扰着Hadoop的倒退,MapReduce的局限次要能够总结为以下几点:
- 抽象层次低,须要手工编写代码来实现,应用上难以上手
- 只提供两个操作,Map和Reduce,表达力欠缺
- 一个Job只有Map和Reduce两个阶段(Phase),简单的计算须要大量的Job实现,Job之间的依赖关系是由开发者本人治理的
- 解决逻辑暗藏在代码细节中,没有整体逻辑
- 两头后果也放在HDFS文件系统中
- ReduceTask须要期待所有MapTask都实现后才能够开始
- 时延高,只实用Batch数据处理,对于交互式数据处理,实时数据处理的反对不够
- 对于迭代式数据处理性能比拟差
比如说,用MapReduce实现两个表的Join都是一个很有技巧性的过程,如下图所示:
因而,在Hadoop推出之后,呈现了很多相干的技术对其中的局限进行改良,如Pig,Cascading,JAQL,OOzie,Tez,Spark等,上面就对一些重要技术进行重点的探讨。
1.Apache Pig
Apache Pig是Hadoop框架中的一部分,Pig提供类SQL语言(Pig Latin)通过MapReduce来解决大规模半结构化数据。而Pig Latin是更高级的过程语言,通过将MapReduce中的设计模式形象为操作,如Filter,GroupBy,Join,OrderBy,由这些操作组成有向无环图(DAG)。例如如下程序就形容了数据处理的整个过程。
visits = load ‘/data/visits’ as (user, url, time);gVisits = group visits by url;visitCounts = foreach gVisits generate url, count(visits);urlInfo = load ‘/data/urlInfo’ as (url, category, pRank);visitCounts = join visitCounts by url, urlInfo by url;gCategories = group visitCounts by category;topUrls = foreach gCategories generate top(visitCounts,10);store topUrls into ‘/data/topUrls’;
而Pig Latin又是通过编译为MapReduce,在Hadoop集群上执行的。上述程序被编译成MapReduce时,会产生如下图所示的Map和Reduce:
Apache Pig解决了MapReduce存在的大量手写代码,语义暗藏,提供操作品种少的问题。相似的我的项目还有Cascading,JAQL等。
2.Apache Tez
Apache Tez,Tez是HortonWorks的Stinger Initiative的的一部分。作为执行引擎,Tez也提供了有向无环图(DAG),DAG由顶点(Vertex)和边(Edge)组成,Edge是对数据的挪动的形象,提供了One-To-One,BroadCast,和Scatter-Gather三种类型,只有Scatter-Gather才须要进行Shuffle。
以如下SQL为例:
SELECT a.state, COUNT(*),AVERAGE(c.price)FROM aJOIN b ON (a.id = b.id)JOIN c ON (a.itemId = c.itemId)GROUP BY a.state
图中蓝色方块示意Map,绿色方块示意Reduce,云状示意写屏障(write barrier,一种内核机制,能够了解为长久的写),Tez的优化次要体现在:
去除了间断两个作业之间的写屏障
去除了每个工作流中多余的Map阶段(Stage)
通过提供DAG语义和操作,提供了整体的逻辑,通过缩小不必要的操作,Tez晋升了数据处理的执行性能。
3.Apache Spark
Apache Spark是一个新兴的大数据处理的引擎,次要特点是提供了一个集群的分布式内存形象,以反对须要工作集的利用。
这个形象就是RDD(Resilient Distributed Dataset),RDD就是一个不可变的带分区的记录汇合,RDD也是Spark中的编程模型。Spark提供了RDD上的两类操作,转换和动作。转换是用来定义一个新的RDD,包含map, flatMap, filter, union, sample, join, groupByKey, cogroup, ReduceByKey, cros, sortByKey, mapValues等,动作是返回一个后果,包含collect, reduce, count, save, lookupKey。
Spark的API非常简单易用,Spark的WordCount的示例如下所示:
val spark = new SparkContext(master, appName, [sparkHome], [jars])val file = spark.textFile("hdfs://...")val counts = file.flatMap(line => line.split(" ")) .map(word => (word, 1)) .reduceByKey(_ + _)counts.saveAsTextFile("hdfs://...")
其中的file是依据HDFS上的文件创建的RDD,前面的flatMap,map,reduceByKe都创立出一个新的RDD,一个简短的程序就可能执行很多个转换和动作。
在Spark中,所有RDD的转换都是是惰性求值的。RDD的转换操作会生成新的RDD,新的RDD的数据依赖于原来的RDD的数据,每个RDD又蕴含多个分区。那么一段程序实际上就结构了一个由相互依赖的多个RDD组成的有向无环图(DAG)。并通过在RDD上执行动作将这个有向无环图作为一个Job提交给Spark执行。
例如,下面的WordCount程序就会生成如下的DAG:
scala> counts.toDebugStringres0: String =MapPartitionsRDD[7] at reduceByKey at <console>:14 (1 partitions) ShuffledRDD[6] at reduceByKey at <console>:14 (1 partitions) MapPartitionsRDD[5] at reduceByKey at <console>:14 (1 partitions) MappedRDD[4] at map at <console>:14 (1 partitions) FlatMappedRDD[3] at flatMap at <console>:14 (1 partitions) MappedRDD[1] at textFile at <console>:12 (1 partitions) HadoopRDD[0] at textFile at <console>:12 (1 partitions)
Spark对于有向无环图Job进行调度,确定阶段(Stage),分区(Partition),流水线(Pipeline),工作(Task)和缓存(Cache),进行优化,并在Spark集群上运行Job。RDD之间的依赖分为宽依赖(依赖多个分区)和窄依赖(只依赖一个分区),在确定阶段时,须要依据宽依赖划分阶段。依据分区划分工作。
Spark反对故障复原的形式也不同,提供两种形式,Linage,通过数据的血缘关系,再执行一遍后面的解决,Checkpoint,将数据集存储到长久存储中。
Spark为迭代式数据处理提供更好的反对。每次迭代的数据能够保留在内存中,而不是写入文件。
Spark的性能相比Hadoop有很大晋升,2014年10月,Spark实现了一个Daytona Gray类别的Sort Benchmark测试,排序齐全是在磁盘上进行的,与Hadoop之前的测试的比照后果如表格所示:
从表格中能够看出排序100TB的数据(1万亿条数据),Spark只用了Hadoop所用1/10的计算资源,耗时只有Hadoop的1/3。
Spark的劣势不仅体现在性能晋升上的,Spark框架为批处理(Spark Core),交互式(Spark SQL),流式(Spark Streaming),机器学习(MLlib),图计算(GraphX)提供一个对立的数据处理平台,这绝对于应用Hadoop有很大劣势。
特地是在有些状况下,你须要进行一些ETL工作,而后训练一个机器学习的模型,最初进行一些查问,如果是应用Spark,你能够在一段程序中将这三局部的逻辑实现造成一个大的有向无环图(DAG),而且Spark会对大的有向无环图进行整体优化。
例如上面的程序:
val points = sqlContext.sql( “SELECT latitude, longitude FROM historic_tweets”) val model = KMeans.train(points, 10) sc.twitterStream(...) .map(t => (model.closestCenter(t.location), 1)) .reduceByWindow(“5s”, _ + _)
这段程序的第一行是用Spark SQL 查寻出了一些点,第二行是用MLlib中的K-means算法应用这些点训练了一个模型,第三行是用Spark Streaming解决流中的音讯,应用了训练好的模型。
三、总结
咱们能够借助于逻辑电路来了解MapReduce和Spark。如果说MapReduce是公认的分布式数据处理的低层次形象,相似逻辑门电路中的与门,或门和非门,那么Spark的RDD就是分布式大数据处理的高层次形象,相似逻辑电路中的编码器或译码器等。
RDD就是一个分布式的数据汇合(Collection),对这个汇合的任何操作都能够像函数式编程中操作内存中的汇合一样直观、简便,但汇合操作的实现却是在后盾分解成一系列Task发送到几十台上百台服务器组成的集群上实现的。最近新推出的大数据处理框架Apache Flink也应用数据集(Data Set)和其上的操作作为编程模型的。
由RDD组成的有向无环图(DAG)的执行是调度程序将其生成物理打算并进行优化,而后在Spark集群上执行的。Spark还提供了一个相似于MapReduce的执行引擎,该引擎更多地应用内存,而不是磁盘,失去了更好的执行性能。
基于此,Spark针对于Hadoop的一些局限进行了解决:
- 抽象层次低,须要手工编写代码来实现,应用上难以上手
=>基于RDD的形象,实数据处理逻辑的代码十分简短 - 只提供两个操作,Map和Reduce,表达力欠缺
=>提供很多转换和动作,很多基本操作如Join,GroupBy曾经在RDD转换和动作中实现 - 一个Job只有Map和Reduce两个阶段(Phase),简单的计算须要大量的Job实现,Job之间的依赖关系是由开发者本人治理的
=>一个Job能够蕴含RDD的多个转换操作,在调度时能够生成多个阶段(Stage),而且如果多个map操作的RDD的分区不变,是能够放在同一个Task中进行 - 解决逻辑暗藏在代码细节中,没有整体逻辑
=>在Scala中,通过匿名函数和高阶函数,RDD的转换反对流式API,能够提供解决逻辑的整体视图。代码不蕴含具体操作的实现细节,逻辑更清晰 - 两头后果也放在HDFS文件系统中
=>两头后果放在内存中,内存放不下了会写入本地磁盘,而不是HDFS - ReduceTask须要期待所有MapTask都实现后才能够开始
=> 分区雷同的转换形成流水线放在一个Task中运行,分区不同的转换须要Shuffle,被划分到不同的Stage中,须要期待后面的Stage实现后才能够开始 - 时延高,只实用Batch数据处理,对于交互式数据处理,实时数据处理的反对不够
=>通过将流拆成小的batch提供Discretized Stream解决流数据 - 对于迭代式数据处理性能比拟差
=>通过在内存中缓存数据,进步迭代式计算的性能
因而,Hadoop MapReduce会被新一代的大数据处理平台代替是技术倒退的趋势,而在新一代的大数据处理平台中,Spark目前失去了最宽泛的认可和反对。
最初,咱们通过Lambda Architecture的一个案例作为完结和补充,Lambda Architecture是一个大数据处理平台的参考模型,如下图所示:
其中蕴含3层,Batch Layer,Speed Layer和Serving Layer,因为Batch Layer和Speed Layer的数据处理逻辑是统一的,如果用Hadoop作为Batch Layer,而用Storm作为Speed Layer,你须要保护两份应用不同技术的代码。
而Spark能够作为Lambda Architecture一体化的解决方案,大抵如下:
Batch Layer,HDFS+Spark Core,将实时的增量数据追加到HDFS中,应用Spark Core批量解决全量数据,生成全量数据的视图
Speed Layer,Spark Streaming来解决实时的增量数据,以较低的时延生成实时数据的视图
Serving Layer,HDFS+Spark SQL(兴许还有BlinkDB),存储Batch Layer和Speed Layer输入的视图,提供低时延的即席查问性能,将批量数据的视图与实时数据的视图合并
通过这个案例,咱们也能够再一次重申上述论断,Spark是能够取代MapReduce从而成为Hadoop零碎中不可或缺的一部分,然而无奈取代Hadoop生态。