在探索之前,我们来看一下hadoop解决了什么问题,hadoop就是解决了大数据(大到单台服务器无法进行存储,单台服务器无法在限定的时间内进行处理)的可靠存储和处理。
hdfs:在由普通或廉价的服务器(或pc)组成的集群上提供高可用的文件存储,通过将块保存多个副本的办法解决服务器或硬盘坏掉的问题。
mapreduce:通过简单的mapper和reducer的抽象提供一个编程模型,可以在一个由几十台或上百台的服务器组成的集群上进行并
发,分布式的处理大量的数据集;而并发,分布式(如:机器间通信)和故障恢复等计算细节隐藏起来。而mapper和reducer的抽象,又是各种各样的
复杂数据处理都可以分解为基本元素。这样,复杂的数据处理可以分解为由多个job(包含一个mapper和一个reducer)组成的有向无环图
(dag),然后每个mapper和reducer放到hadoop集群上执行,就可以得出如下图所示的结果:

在hadoop的源码中,提供了一个很经典的例子:wordcount,具体源码可以参见上篇文章,如果对
mapreduce不熟悉,通过该示例对mapreduce进行一些了解对理解下文会由帮助。在mapreduce中,shuffle是一个非常重要的过
程,正是有了看不见的shuffle过程,才可以使在mapreduce之上写数据处理的开发者完全感觉不到分布式和并发的存在。
注:广义的shuffle是指图中在map和reduce之间的一系列过程。
mapreduce存在以下局限,使用起来比较困难。
抽象层次低,需要手工编写代码来完成,使用上难以上手,入门门槛较高。
只提供两个操作,map和reduce,表达的力度不够。
一个job只有map和reduce两个阶段,复杂的计算需要大量的job来完成。job之间的依赖关系是由开发者自己来管理的。
处理逻辑隐藏在代码细节中,没有整体逻辑。
中间结果也放在hdfs文件系统中。
reducetask需要等待所有的maptask都完成后才可以开始。
时延高,只适用batch数据处理,对于交互式数据处理,实时数据处理的支持不够。
对于迭代式数据处理性能比较差。
举个例子,用mapreduce实现表与表之间的join,都是一个很需要技巧来处理的过程,如下图:
因此,在hadoop之后,出现来很多相关技术对其中的局限进行改进,如:hive,oozie,tez,spark,storm等等。
这里就不多赘述了。hive是一种底层封装了hadoop的数据仓库处理工具,使用类sql的hivesql语言实现数据查询,所有hive的数据都存储
在hdfs中。hive在加载数据过程中不会对数据进行任何的修改,只是将数据移动到hdfs中hive的指定目录下,因此,hive不支持对数据的改写
和添加,所有的数据都是在加载的时候确定的。
hive解决类mapreduce存在的大量手写代码,语义隐藏,提供操作种类少的问题。类似的项目还有pig,jaql等。
tez是hortonworks的stinger
initiative的的一部分。作为执行引擎,tez也提供了有向无环图(dag),dag由顶点(vertex)和边(edge)组成,edge是对
数据的移动的抽象,提供了one-to-one,broadcast,和scatter-gather三种类型,只有scatter-gather才需要
进行shuffle。
示例:
tez的优化主要体现在:
去除了连续两个任务之间的写屏障
去除了每个工作流中多余的map阶段
通过提供dag语义和操作,提供了整体的逻辑,通过减少不必要的操作,tez提升了数据处理的执行性能。
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支持故障恢复的方式也不同,提供两种方式,linage,通过数据的血缘关系,再执行一遍前面的处理,checkpoint,将数据集存储到持久存储中。
spark的api非常简单易用,使用spark,wordcount的示例如下所示:
其中的file是根据hdfs上的文件创建的rdd,后面的flatmap,map,reducebyke都创建出一个新的rdd,一个简短的
程序就能够执行很多个转换和动作。在spark中,所有rdd的转换都是是惰性求值的。spark的任务是由相互依赖的多个rdd组成的有向无环图
(dag),每个rdd又包含多个分区,当在rdd上执行动作时,spark才对任务进行调度。
spark对于有向无环图对任务进行调度,确定阶段,分区,流水线,任务和缓存,进行优化,并在spark集群上运行任务。rdd之间的依赖分为宽依赖(依赖多个分区)和窄依赖(只依赖一个分区),在确定阶段时,需要根据宽依赖划分阶段。根据分区划分任务。
spark为迭代式数据处理提供更好的支持。每次迭代的数据可以保存在内存中,而不是写入文件。
spark的性能相比hadoop有很大提升,2014年10月,spark完成了一个daytona gray类别的sort benchmark测试,排序完全是在磁盘上进行的,与hadoop之前的测试的对比结果如表格所示:
原图链接地址:http://databricks.com/blog/2014/11/05/spark-officially-sets-a-new-record-in-large-scale-sorting.html
从表格中可以看出排序100tb的数据(1万亿条数据),spark只用了hadoop所用1/10的计算资源,耗时只有hadoop的1/3。
spark的优势不仅体现在性能提升上的,spark框架为批处理(spark core),交互式(spark sql),流式(spark
streaming),机器学习(mllib),图计算(graphx)提供一个统一的平台,这相对于使用hadoop有很大优势。
那么spark解决了hadoop的哪些问题?
抽象层次低,需要手工编写代码来完成,使用上难以上手。
=>基于rdd的抽象,实数据处理逻辑的代码非常简短。
只提供两个操作,map和reduce,表达力欠缺。
=>提供很多转换和动作,很多基本操作如join,groupby已经在rdd转换和动作中实现。
一个job只有map和reduce两个阶段,复杂的计算需要大量的job完成,job之间的依赖关系是由开发者自己管理的。
=>一个job可以包含rdd的多个转换操作,在调度时可以生成多个阶段,而且如果多个map操作的rdd的分区不变,是可以放在同一个task中进行。
处理逻辑隐藏在代码细节中,没有整体逻辑。
=>在scala中,通过匿名函数和高阶函数,rdd的转换支持流式api,可以提供处理逻辑的整体视图。
代码不包含具体操作的实现细节,逻辑更清晰。 中间结果也放在hdfs文件系统中。
=>中间结果放在内存中,内存放不下了会写入本地磁盘,而不是hdfs。
reducetask需要等待所有maptask都完成后才可以开始
=>它允许用户单独为map task和reduce task设置不同的资源,进而细粒度控制任务占用资源量,有利于大作业的正常平稳运行。
=>通过将流拆成小的batch提供discretized stream处理流数据。
=>通过在内存中缓存数据,提高迭代式计算的性能。
这篇文章就分享到这里,若在研究的过程中有什么疑问,可以加群讨论或发送邮件给我,我会尽我所能为您解答,与君共勉!