Hadoop面试整理

(1)Hadoop1.x和2.x之间的区别

Hadoop 1.0内核主要由两个分支组成:MapReduce和HDFS,在高可用、扩展性等方面存在问题

1)HDFS存在的问题

  1.NameNode单点故障,难以应用于在线场景。

  2.NameNode压力过大,且内存受限,影响扩展性。

2)MapReduce存在的问题

  1.JobTracker存在单点故障问题;同时因为JobTracker监控每个作业的运行状态和对资源进行管理,压力很大。

  2.难以支持除MapReduce之外的计算框架,比如Spark、Strom等。

Hadoop2.x主要解决单点故障和内存受限问题。  

1)Hadoop 2.0中新引入的资源管理系统YARN,它的引入使得Hadoop不再局限于MapReduce一类计算,而是支持多样化的计算框架。它由两类服务组成,分别是ResourceManager和NodeManager。

3)解决HDFS1.x中单点故障。通过主备NameNode使用HA解决单点故障问题。如果主NameNode发生故障,则切换到备NameNode之上。

4)解决HDFS1.x内存受限问题,使用联邦HDFS机制,内存水平扩展,支持多NameNode。每个NameNode分管一部分目录,所有NameNode共享所有DataNode存储资源。

5)主NameNode对外提供服务,备NameNode同步主NameNode元数据,以待切换。

6)所有DataNode同时向两个NameNode汇报数据块信息。

注意:辅助Namenode的角色被备用namenode所包含,备用namenode充当辅助Namenode为活动的namenode命令空间设置周期性检查点。

(2)Hadoop中的HDFS、MapReduce和YARN的单点故障解决方案架构是完全一致的,分为手动模式和自动模式。

  手动模式:通过命令实现主备之间的切换,可以用在HDFS升级等场合。

自动模式:基于Zookeeper。Zookeeper Failover Controller【ZKFC】会监控NameNode的健康状态,并向Zookeeper注册NameNode,当NameNode挂掉后,ZKFC为NameNode竞争锁,获得ZKFC锁的NameNode变为active。

Hadoop中高可用的组件如下:

1)MasterHADaemon:与Master服务运行在同一个进程中,可接收外部RPC命令,以控制Master服务的启动和停止;

2)SharedStorage:共享存储系统,active master将信息写入共享存储系统,而standby master则读取该信息以保持与active master的同步,从而减少切换时间。常用的共享存储系统有zookeeper(被YARN HA采用)、HDFS(被MapReduce HA采用)和类zookeeper系统(被HDFS HA采用)。

3)ZKFailoverController:基于Zookeeper实现的切换控制器,主要由两个核心组件构成:ActiveStandbyElector和HealthMonitor,其中,ActiveStandbyElector负责与zookeeper集群交互,通过尝试获取全局锁,以判断所管理的master进入active还是standby状态;HealthMonitor负责监控各个活动master的状态,以根据它们状态进行状态切换。

4)Zookeeper集群:核心功能通过维护一把全局锁控制整个集群有且仅有一个active master。

(3)实现高可用可能会出现的问题:

脑裂:脑裂是指在主备切换时,由于切换不彻底或其他原因,导致客户端和Slave误以为出现两个active master,最终使得整个集群处于混乱状态。解决脑裂问题,通常采用隔离(Fencing)机制,包括三个方面:

1)共享存储fencing:确保只有一个Master往共享存储中写数据。

2)客户端fencing:确保只有一个Master可以响应客户端的请求。

3)Slave fencing:确保只有一个Master可以向Slave下发命令。

切换对外透明:Hadoop应保证所有客户端和Slave能自动重定向到新的active master上,这通常是通过若干次尝试连接旧master不成功后,再重新尝试链接新master完成的。  

Hadoop公共库中有哪几种隔离机制:

1)sshfence:sshfence是指通过ssh登陆目标Master节点上,使用命令fuser将进程杀死(通过tcp端口号定位进程pid,该方法比jps命令更准确)

2)shellfence:shellfence是指执行一个用户事先定义的shell命令(脚本)完成隔离

(4)HDFS(Hadoop Distributed File System)分布式文件系统的介绍:

HDFS具有高容错性,并提供了高吞吐量的数据访问,非常适合大规模数据集上的应用,优点如下:

1)高容错性,保存多个副本,且提供容错机制。副本丢失或宕机自动恢复。默认存3份。

2)流式数据访问,一次写入,多次读取,高吞吐量,所以可以同时处理大量数据。

3)可以存储大量文件,如PB级。

4)运行在廉价的机器上,通过副本提高可靠性,提供了容错和恢复机制

HDFS中的相关组件:

(1)数据块:HDFS也有默认块的概念,磁盘块大小一般为512字节,而HDFS块大小默认为128MB,HDFS上的文件被划分为块大小的多个分块,作为独立的存储单元。与面向单一磁盘的文件系统不同的是,HDFS中小于一个块大小的文件不会占据整个块的空间。如一个1MB的文件存储在一个128MB块中时,文件只是使用1MB的磁盘空间。

  1)HDFS中块的大小为什么比磁盘块大:目的是为了最小化寻址开销,如果块足够大,从磁盘传输的时间会明显大于定位这个块开始位置所需的时间,因此传输一个由多个快组成的大文件的时间取决于磁盘传输速率。

  2)为什么块不能设置过大:MR中的map认为一般处理一个块中数据,如果任务数较少,作业运行速度将会比较慢。

  3)使用块作为HDFS的最小存储单元的好处:

    1.一个文件的大小可以大于网络中任意磁盘的容量,文件的所有块并不需要存储在同一个磁盘中。

    2.利用块而不是整个文件作为存储单元可以简化存储管理(块大小固定,单个磁盘能存储多少个块就相对容易),消除对元数据的顾虑(块只存储真正的数据,而文件的元数据不会与块一同存储,其他系统可以单独管理这些元数据)

    3.块适合数据备份进而提供容错能力和提高可用性,默认块的备份为3个,确保数据不会丢失,发现一个块不可用,系统会从其他地方读取另外一个副本。

(2)namenode和datanode

  namenode:namenode管理文件系统的命名空间。它维护着文件系统树及整棵树内的所有文件和目录。这些信息以两个文件形式永久保存在本地磁盘上:命名空间镜像文件和编辑日志文件。namenode也记录着每个文件中各个块所在的数据节点信息,但是它并不会永久保存块的位置信息,因为这些信息会在系统启动时根据数据节点信息重建。

  datanode:一个数据块在datanode上以文件形式存储在磁盘上,包括两个文件,一个是数据本身,一个是数据块元数据即数据块的长度,块数据的校验和,以及时间戳。心跳是每3秒一次,心跳返回结果带有namenode给该datanode的命令如复制块数据到另一台机器,或删除某个数据块。如果超过10分钟没有收到某个datanode的心跳,则认为该节点不可用。

  1)namenode的发生故障的解决方案

    1.在非namenode节点上备份那些组成文件系统元数据持久状态的文件,然后利用备份namenode执行这些文件(冷启动)。

    2.利用检查点进行故障恢复即利用辅助namenode,辅助namenode不能充当namenode,但是备用namenode可以充当辅助namenode。

  2)辅助namenode为namenode创建检查点机制

    1.secondNamenode请求主namenode停止使用正在进行中的edit文件,这样新的编辑操作记录到一个新文件中edit.new

    2.secondNamenode从主nomanode获取最近的fsimage和edit文件.

    3.SecondNamenode将fsimage文件载入内存,逐一执行edit文件中的操作.创建新的合并的fsimage.

    4.辅助namenode将新的fsimage文件发送回namenode,主namenode将其保存为临时的.ckpt

    5.主namenode重新命名为临时的fsimage文件,以便以后使用.

  3)辅助namenode的作用:SecondaryNameNode的重要作用是定期通过编辑日志文件合并命名空间镜像,以防止编辑日志文件过大。SecondaryNameNode一般要在另一台机器上运行,因为它需要占用大量的CPU时间与namenode相同容量的内存才可以进行合并操作。它会保存合并后的命名空间镜像的副本,并在namenode发生故障时启用。

  4)DataNode发生故障的处理方案步骤:

    1.排查datanode机器的硬件、网络等环境,确认是否是datanode本身节点问题;

    2.关闭处于dead状态节点的datanode、nodemanager进程即hadoop-daemon.sh stop datanode,yarn-daemon.sh stop nodemanager

    3.重启dead状态节点的datanode、nodemanager进程即hadoop-daemon.sh start datanode,yarn-daemon.sh start nodemanager。

  5)hdfs上传写数据的过程:

    1.client跟NameNode通信请求上传文件,NameNode检查目标文件是否存在以及client是否有新建此文件的权限.

    2.若通过检查,NameNode就会为创建一条记录,记录该新建文件的信息.若未通过检查就会抛出异常.

    3.然后NameNode向客户端返回可以新建文件的信息以及相应的一组datanode,Client就近原则请求3台中的一台DataNode 1上传数据(本质上是一个RPC调用,建立pipeline)DataNode 1收到请求会继续调用DataNode 2,然后DataNode 2调用DataNode 3,将整个pipeline(管线)建立完成,然后逐级返回客户端。

    4.Client将文件分成一个个数据包写入到数据队列中,往DN1上传第一个块,以数据包为单位.DN1收到一个数据包就会传给DN2,DN2传给DN3。

    5.当DN  3写完最后一个pocket时,就会返回确认消息给DN2,DN2返回确认消息给DN  1,然后返回给客户端,最后由客户端返回给namenode.

  6)hdfs读取数据的过程:

    1.client与NameNode通信查询元数据,找到文件块所在的DataNode,namenode将相应的元数据信息返回给client.

    2.client根据元数据信息挑选一台DataNode(网络拓扑上的就近原则,如果都一样,则随机挑选一台DataNode),请求建立socket流,以packet为单位进行发送.

    3.DataNode开始发送数据,客户端以packet为单位接收,先在本地缓存,然后写入目标文件。

(5)YARN介绍

yarn通过两类长期运行的守护进程提供自己的核心服务:管理集群上的资源使用的资源管理器(ResourceManager),以及运行在集群中的所有节点上且能够启动和监控容器的节点管理器(nodeManager).容器Container 是 YARN 中的资源抽象,它封装了某个节点上的多维度资源,如内存、CPU、磁盘、网络等,当AM向RM申请资源时,RM为AM返回的资源便是用Container表示的。YARN会为每个任务分配一个Container,且该任务只能使用该Container中描述的资源。

通过将资源管理和应用程序管理两部分分剥离开,分别由ResouceManager和ApplicationMaster负责,其中,ResouceManager专管资源管理和调度,而ApplicationMaster则负责与具体应用程序相关的任务切分、任务调度和容错等,每个应用程序对应一个ApplicationMaster.  YARN的运行机制:

1)YARN的运行机制

  1.客户端提交application到资源管理器,要求资源管理器运行ApplicationMaster进程.

  2.资源管理器找到一个能够在容器中启动application的节点管理器.如果是一个简单的计算过程,就会在资源管理器所处的容器中进行计算,将计算结果返回给客户端.

  3.当计算任务比较复杂时,就会向资源管理器请求更多的节点的容器,以用于运行一个分布式计算.

2)YARN是在什么层面上进行调度的:MR和Spark作为YARN的应用运行在集群计算层和集群的存储层上的.

3)YARN的资源调度措施即调度器

  1.FIFO调度器(FIFO Scheduler):将应用放置在第一个队列中,然后按照提交的顺序(先进先出)运行应用。首先为队列中第一个应用的请求分配资源,第一个应用的请求被满足后再一次为队列中下一个应用服务。优点是简单易懂不需要任何配置,但是不适合共享集群,当使用FIFO调度器(i)时,小作业一直被阻塞,直至大作业完成。

  2.容量调度器(Capacity Scheduler):一个独立的专门队列保证小作业一提交就可以启动,由于队列容量是为那个队列中的作业所保留的,因此这种策略是以整个集群的利用率为代价的。这意味着与使用FIFO调度器相比,大作业执行的时间要长。

  3.和公平调度器(Fair Scheduler):公平调度器不需要预留一定量的资源,因为调度器会在所有运行的作业之间动态平衡资源。第一个(大)作业启动时,它是唯一运行的作业,因而获得集群中所有的资源。当第二个(小)作业启动时,它被分配到集群的一半资源,这样每个作业都能公平共享资源。

4)YARN的资源隔离方案:

  1.对于CPU而言,它是一种“弹性”资源,使用量大小不会直接影响到应用程序的存亡,因此CPU的资源隔离方案采用了Linux Kernel提供的轻量级资源隔离技术ControlGroup;yarn使用cgroup的两种方式来控制cpu资源分配分别是严格按核数隔离资源和按比例隔离资源.

  2.内存的隔离:对于内存而言,它是一种“限制性”资源,使用量大小直接决定着应用程序的存亡,Cgroup会严格限制应用程序的内存使用上限,一旦使用量超过预先定义的上限值,就会将该应用程序“杀死”,因此无法使用Cgroup进行内存资源隔离,而是选择了线程监控的方式。

(6)MapReduce的shuffle过程。

每个map task都有一个内存缓冲区,存储着map的输出结果,当缓冲区快满的时候需要将缓冲区的数据以一个临时文件的方式存放到磁盘,当整个map task结束后再对磁盘中这个map task产生的所有临时文件做合并,生成最终的正式输出文件,然后等待reduce task来拉数据。

shuffle优化核心:减少拉取数据的量(io操作)及尽量使用内存而不是磁盘。

每个map任务都有一个环形内存缓冲区用于存储任务输出,缓冲区的作用是批量收集map结果,减少磁盘IO的影响。整个环形内存缓冲区就是一个字节数组,默认大小为100MB,环形缓冲区分为两个部分,数据区和索引区。数据区是存放用户真实的数据,索引区存放数据对应的key值,partition和位置信息。为防止map task的输出结果很多而撑爆内存,需要在达到设定的环形缓冲区的阈值后将缓冲区中的数据临时写入磁盘。

1)shuffle的开始和结束时间:

  开始时间:map执行完成有输出文件产生,shuffle开始;

  结束时间:reduce输入文件最终确定了,shuffle结束;

2)shuffle的前半段:

  1.溢写之前:在经过mapper的运行后,mapper的输出结果是key/value对。MapReduce提供Partitioner接口,它根据key决定当前的这对输出数据最终应该交由哪个reductask处理。默认是对key进行 hashcode后再以reduce task数量取模。在每个分区之中,后台线程就会按在内存中对key做排序,如果有一个combiner函数,就在排序后的输出上运行。(运行combiner函数使map的结果更加紧凑,因此减少到写到磁盘上的数据和传递给reduce的数据)将map输出结果写入到环形缓冲区中。

  2.溢写开始:当缓冲区的数据已经达到阈值,然后溢写线程启动,锁定这80%的内存,执行溢写过程。Map task的输出结果还可以往剩下的20%内存中写,互不影响。 

  3.溢写之后:每次溢写会在磁盘上生成一个溢写文件,磁盘上可能会有多个溢写文件存在。在map task完成之前,溢出文件被合并成一个已分区且已排序的输出文件。

3)shuffle的后半段:

  1.Copy过程:简单地拉取数据,将Copy过来的数据会先放入reduce端的内存缓冲区中。Reduce进程启动一些数据copy线程(Fetcher),拉取存储在磁盘中的map 输出结果

  2.Merge阶段:合并不同map端copy来的数值。

  3.Reducer的输入文件:不断地merge后,最后会生成一个“最终文件”,这个文件可能存在于磁盘上,也可能存在于内存中。对我们来说,当然希望它存放于内存中,直接作为Reducer的输入,但默认情况下,这个文件是存放于磁盘中的。

(7)mapreduce中的排序

Map Task和Reduce Task都会对数据按照key排序,MapReduce中使用了两种排序算法:快速排序和优先队列。在Map和Reduce Task的缓冲区使用的是快速排序,而对磁盘上的IFile文件合并使用的是优先队列。

优先队列:本质上是最小堆,在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (first in, largest out)的行为特征。通常采用堆数据结构来实现。优先队列的两个核心函数就是 upHeap() 和 downHeap(),所有优先队列的操作都是围绕这两个函数进行的。upHeap()函数名里的up代表目的方向,实际是从down 到 up 的 过程。downHeap()函数名里的down也代表目的方向,实际是从up到 down 的 过程。upHeap() 是建小顶堆,downHeap() 重新调整节点,重新成为小顶堆。

相关推荐