1.HDFS
优势:(1) 处理超大文件(2)运行于廉价的商用机器集群上(3)高容错性和高可靠性,通过副本机制实现。(4)流式的访问数据,HDFS的设计建立在更多地响应」次写人、多次读写”任务的基础上,这意味着一个数据集一由数据源生成,就会被复制分发到不同的存储节点中,然后响应各种各样的数据分析任务请求。在多数情况下,分析任务都会涉及数据集的大部分数据,也就是说,对HDFS来说,请求读取整个数据集比请求读取单条记录会更加高效。
局限性:(1)不适合低延迟数据访问。(2)无法高效存储大量小文件。在HDFS中,需要用NameNode来管理文件系统的元数据,以相应客户端请求返还文件的位置,而这些元数据都存放在内存中,所以文件系统所能容忍的文件数目是由NameNode内存大小决定的。可以通过构建NameNode集群的方式来扩充文件数。(3)不支持多用户写入和随机文件修改。在HDFS的一个文件中只有一个写入者,而且写操作只能在文件末尾完成,即只能执行追加操作。目前HDFS还不支持多个用户对同一文件的写操作,也不支持在文件任意位置进行修改。
HDFS的体系结构,HDFS采用了从(Master/Slave)的结构模型,一个HDFS集群是由一个NameNode和若干个DataNode组成的,其中NameNode作为主服务器,管理文件系统的命名空间(即文件有几块,分别存储在哪个节点上等)和客户端对文件的访问操作;集群中的DataNode管理存储的数据。HDFS允许用户以文件的形式存储数据。从内部来看,文件被分为若干数据块,而且这若干个数据块存放在一组DataNode上。NameNode执行文件系统的命名空间操作,比如打开、关闭、重命名文件或目录等,它也负责数据块到具体DataNode的映射。DataNode负责处理文件系统客户端的文件读写请求,并在NameNode的统一调度下进行数据块的创建、删除和复制工作。NameNode是所有HDFS元数据的管理者,用户数据不会经过NameNode。
、、
2.MapReduce
MapReduce也是采用的Master/Slave的主从架构。MapReduce包含4个组成部分,分别为Client、JobTracker、TaskTracker和Task。
(1)Cilent
每个Job都会在用户端通过Client类将应用程序以及配置参数Configuration打包成JAR文件存储在HDFS中,并把路径提交到JobTracker的Master服务,然后由Master创建每一个Task(即MapTask和ReduceTask)将它们分发到各个TaskTracker服务中去执行。
(2)JobTracker
JobTracker负责资源监控和作业调度。JobTracker监控所有的TaskTracker与Job的健康状况,一旦发现失败就将对应的任务转移到其他节点;同时,JobTracker会跟踪任务的执行进度、资源使用情况,并将这些信息告诉任务调度器,而调度器会在资源出现空闲时,选择合适的任务使用这些资源。在Hadoop中,任务调度器是一个可插拔的模块,用户可
以根据自己的需要设计相应的调度器。
(3)TaskTracker
TaskTracker会周期性地通过Hearbeat将本节点上的资源使用情况和任务的运行进度汇报给JobTracker,同时接收JobTracker发送过来的命令并执行相应的操作(如启动新的任务、杀死任务等)。TaskTracker使用solt来衡量划分本节点上的资源量。“slot”代表单位的计算资(CPU、内存等)。一个task获取到一个slot后才有机会运行,而Hadoop调度器的作用就是将各个TaskTracker上的空闲slot分配给Task使用。slot分为Mapslot和Reduceslot两种,分别供M叩Task和ReduceTask使用。TaskTracker通过slot数目(可配置参数)限定Task的并发度。
(4)Task
Task分为MapTask和ReduceTask两种,均由TaskTracker启动。HDFS以固定大小的block为基本单位存储数据,而对于MapReduce而言,其处理单位是split。
3.MapReduce任务提及详解
客户端将Job(也就是MapReduce任务)提交到JobTracker上,JobTracker会为该Job分配一个Id,然后检查Job的输出目录和输入文件是否存在,不存在则抛出错误。同时,JobTracker会根据输入文件计算输入分片(input split),这些都检查通过后,JobTracker就会配置Job需要的资源并分配资源,然后JobTracker就会初始化作业,也就是将Job放入一个内部的队列,让配置好的作业调度器能调度到这个作业,作业调度器会初始化这个Job,初始化就是创建一个正在运行的Job对象(封装任务和记录信息),以便JobTracker跟踪Job的状态和进程。
该job被作业调度器调度时,作业调度器会获取输入分片信息,每个分片创建一个Map任务,并根据TaskTracker的忙闲情况和空闲资源分配Map任务和Reduce任务到TaskTracker,同时通过心跳机制也可以监控到TaskTracker的状态和进度,也能计算出整个Job的状态和进度。当JobTracker获得了最后一个完成指定任务的TaskTracker操作成功的通知时候,JobTracker会把整个Job的状态设置为成功,然后当查询Job运行状态时(注意:这里是异步操作),客户端会查到Job完成的通知。如果Job中途失败,MapReduce也会有相应的机制处理。一般而言,如果不是程序员程序本身有bug,MapReduce错误处理机制都能保证提交的Job能正常完成。
4.MapReduce内部执行原理详解
1.输入分片
进行Map计算之前,MapReduce会根据输入文件计算输入分片。每个输入分片对应一个Map务,输入分片存储的并非数据本身,而是一个分片长度和-个记录数据的位置的数组。输入分片往往和HDFS的block(块)关系很密切,假如设定HDFS的块的大小是64MB,如果输人只有一个文件大小为150MB,那么MapReduce会把此大文件切分为三片(分别为64MB、64MB和22MB),同样,如果输入为两个文件,其大小分别是20MB和IOOMB,那么MapReduce会把20MB文件作为一个输入分片,IOOMB则切分为两个即64MB和36MB的输入分片。对于上述实例文件l和2,由于非常小,因此分别被作为splitl和split2输人Map任务1和2中(此处只为说明问题,实际处理中应将小文件进行合并,否则如果输入多个文件而且文件大小均远小于块大小,会导致生成多个不必要的Map任务,这也是MapReduce优化计算的一个关键点)。
2.Map
在Map阶段,各个Map任务会接收到所分配到的split,并调用Map函数,逐行执行并输出键值对。
3.Combiner阶段
Combiner阶段可选的。Combiner其实也是一种Reduce操作,但它是一个本地化的Reduce操作,是Map运算的本地后续操作,主要是在Map计算出中间文件前做一个简单的合并重复键值的操作,例如上述文件1中data出现了4次,Map计算时如果碰到一个data的单词就会记录为1,这样就重复计算了4次,Map任务输出就会有冗余,这样后续处理和网络传输都被消费不必要的资源,因此通过Combiner操作可以解决和优化此问题,但这一操作是有风险的,使用它的原则是Combiner的输出不会影响到Reduce计算的最终输入,例如,如果计算只是求总数、最大值及最小值,可以使用Combiner操作,但是如果做平均值计算使用Combiner,最终的Reduce计算结果就会出错。
4.Shuffle阶段
Map任务的输出必须经过一个名叫Shuffle的阶段才能交个Reduce处理。Shuffle阶段是MapReduce的核心,Shuffle阶段的性能直接影响整个MapReduce的性能。
Shuffle阶段包含在Map和Reduce两个阶段,在Map阶段的Shuffle阶段是对Map的结果进行分区(partition)、排序(sort)和分隔(spill),然后将属于同一个分区的输出合并在一起(merge)到磁盘上个,同时按照不同的分区发送给对应的Reduce(Map输出的划分和Reduce任务的对应关系由JobTracker确定)的整个过程。Reduce阶段的Shuffle又会将各个Map输出的同一个分区划分的输出进行合并,然后对合并的结果进行排序,最后交给Reduce处理整个过程。
(1)Map阶段的Shuffle
通常MapReduce计算的都是海量数据,而且Map输出还需要对结果进行排序,内存开销很大。以此完全在内存中完成是不能的也是不现实的,所以Map输出时会在内存中开启一个环形内存缓存区,并且在配置文件中为这个缓存区设置一个阈值(默认为80%)。同时,Map还为输出操作启动了一个守护线程,如果缓存区的内存使用达到了阈值,那么这个守护线程就会将80%的内容写到磁盘上,这个过程就是分隔,另外的20%内存可以供Map输出继续使用,写入磁盘的和写入内存的操作互不干扰的,如果缓存区被撑满了,那么Map就会阻塞写入内存操作,待写入磁盘操作完成后再继续执行写入内存操作。
缓存区内容分隔到磁盘前,会首先进行分区操作,分区的数目由Reduce的数目决定。如果Reduce的数目为2,那么分区数就是2,然后对于每个分区,后台线程还会按照键值对需要写出的数据进行排序,如果配置了Combine函数,还会进行Combine操作,以使得更少的数据写入磁盘并发送给Reduce。
每次的分隔操作都会生成一个分隔文件,全部的Map输出完成后,可能会有很多的分隔文件,因此在Map任务结束前,还要进行合并操作,即将这些分隔文件按照分区合并为单独的件。在合并过程中,同样也会进行排序,如果定义了Combiner函数,也会进行combiner操作。
至此,Map阶段的所有工作都已结束,最终生成的文件也会存放在TaskTracker能访问的某个本地目录内。每个ReduceTask不断地从JobTracker那里获取MapTask是否完成的信息,如果ReduceTask得到通知,获知某台TaskTracker上的MapTask执行完成,Shuffle的后半段过程,也就是Reduce阶段的Shuffle,便开始启动。
(2)Reduce的shuffle
Shuffle在Reduc阶段可以分为三个阶段:CopyMap输出、Merge阶段和Reduce处理
1)CopyMap输出:Map任务完成后,,会通知父TaskTracker状态已完成,TaskTracker进而通知JobTracker(都是通过心跳完成).对于Job来说,JobTracker记录了Map输出和TaskTracker的映射关系。同时Reduce也会定期向JobTracker获取Map的输出与否已经输出位置,一定拿到输出位置,Reduce任务就会启动Copy线程,通过HTTP方式请求Map Task所在的TaskTracker获取其输出文件。因为Map Task早已结束,这些文件就被TaskTracker存储在mapTask所在的本地磁盘中。
2)Merge阶段:此处合并和Map阶段合并类似,复制过来的数据首先会放入内存缓冲区中,这里的内存缓存区大小比Map阶段和灵活许多,它是基于JVM的heap size设置的,因为Shuffle阶段Reduce Task并不运行,因此大部分的内存应该是给Shuffle使用。同时Shuffle的合并阶段根据要处理的数据量不同,也看有分隔磁盘的过程,如果设置了Combiner函数,Combiner操作也会进行。假如map有3个 reduce有2个 那么一般情况下每一个reduce需要合并3个Map文件。合并:MapTaskl对于offline键的值为2,而MapTask2的offline键值为1,那么合并就是将offline的键值合并为group,本例即为<offline,{2,1}>。
3)Reduce Task的输入:不断合并后,最终会生成一个最终结果(可能在内存汇总,也可能在磁盘),到此Reduce Task的输入准备完毕,下一步就是真正的Reduce操作。
5.Reduce 阶段
过Map和Reduce阶段的Shuffle过程后,Reduce任务的输入终于准备完毕,相关的数据已经被合并和汇总,Reduce任务只需调用Reduce函数即可。