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等。

(3)Hadoop2.x主要解决单点故障和内存受限以及支持多种计算框架。  

  1)解决HDFS1.x中单点故障:通过主备NameNode使用HA解决单点故障问题。如果主NameNode发生故障,则切换到备NameNode之上。主NameNode对外提供服务,备NameNode同步主NameNode元数据,以待切换。

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

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

2、HDFS(Hadoop Distributed File System)分布式文件系统:

(1)分布式与集群之间的关系

  1)分布式:分布式是指多个系统协同合作完成一个特定任务的系统;把一个大的问题拆分为多个小的问题,并分别解决,最终协同合作。分布式的主要工作是分解任务,将职能拆解。

  2)集群:主要的使用场景是为了分担请求的压力,也就是在几个服务器上部署相同的应用程序,来分担客户端请求。集群主要是简单加机器解决问题,对于问题本身不做任何分解;

  3)区别:

   a、将一套系统拆分成不同子系统部署在不同服务器上叫分布式,然后部署多个相同的子系统在不同的服务器上叫集群,部署在不同服务器上的同一个子系统应做负载均衡。 

   b、分布式:一个业务拆分为多个子业务,部署在多个服务器上 

   c、集群:同一个业务,部署在多个服务器上。

  4)分布式的三大要素

   a、强一致性C:即在分布式系统中的同一数据多副本情形下,对于数据的更新操作体现出的效果与只有单份数据是一样的。

   b、可用性A:客户端在任何时刻对大规模数据系统的读/写操作都应该保证在限定延时内完成;

   c、分区容忍性(P):系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。

  5)为什么分布式环境下CAP三者不可兼得呢?

   对于分布式环境下,P是必须要有的,所以该问题可以转化为:如果P已经得到,那么C和A是否可以兼得?可以分为两种情况来进行推演:

   a、如果在这个分布式系统中数据没有副本,那么系统必然满足强一致性条件,因为只有独本数据,不会出现数据不一致的问题,此时C和P都具备。但是如果某些服务器宕机,那必然会导致某些数据是不能访问的,那A就不符合了。

   b、如果在这个分布式系统中数据是有副本的,那么如果某些服务器宕机时,系统还是可以提供服务的,即符合A。但是很难保证数据的一致性,因为宕机的时候,可能有些数据还没有拷贝到副本中,那么副本中提供的数据就不准确了。

   根据具体业务来侧重于C或者A,对于一致性要求比较高的业务,那么对访问延迟时间要求就会低点;对于访问延时有要求的业务,那么对于数据一致性要求就会低点。

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

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

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

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

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

(3)HDFS中的相关组件:

  1)namedode与secondNamenode

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

  2)辅助namenode:辅助Namenode的角色被备用namenode所包含。

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

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

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

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

   备用namenode如何代替主namenode:基于Zookeeper,Zookeeper Failover Controller(ZKFC)会监控NameNode的健康状态,NameNode会向Zookeeper注册,当主NameNode挂掉后,ZKFC为NameNode竞争锁,获得ZKFC锁的NameNode变为active。

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

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

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

   c、SecondNamenode将fsimage文件载入内存,逐一执行edit文件中的操作.创建新的fsimage即fsimage.ckpt。

   d、辅助namenode将新的fsimage文件发送回namenode,NameNode将fsimage.ckpt与edits.new文件分别重命名为fsimage与edits,然后更新fsimage。

  5)datanode

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  6)hdfs读取数据的过程:

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

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

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

3、MapReduce

(1)mapreduce的过程

  1)split过程:在map task执行时,它的输入数据来源于HDFS的block。在MapReduce中,map task只读取split。Split与block的对应关系可能是多对一,默认是一对一。输入分片存储的并不是数据本身,而是一个分片长度和一个记录数据的位置的数组。inputFormat一行一行的读取文件,按行分割形成<key,value>对。其中key为偏移量,value为每行数据内容。

  2)partition过程:在经过mapper的运行后,输出结果是一个key/value对,MapReduce提供Partitioner接口,它根据key决定当前的这对输出数据最终应该交由哪个reduce task处理。默认是对key hash后再对reduce task数量取模。之后key/value对以及Partition的结果将会被序列化写入map中环形内存缓冲区中,缓冲区的作用是批量收集map结果,减少磁盘IO的影响。

  3)溢写过程:map中的环形内存缓冲区其实是字节数组,是有大小限制的,默认是100MB。当达到环形缓冲区的阈值即80%时,map的输出结果依然会写入到剩余20%的缓冲区中同时会启动溢写线程,对环形缓冲区中80%的数据按照被序列化的后key+partitionsID进行排序。如果有combiner函数就将有相同key的value加起来,减少溢写到磁盘的数据量,使输出结果更加紧凑。

  4)merger溢写文件:如果map的输出结果非常大,则会产生多个溢出文件。此时会将多个溢写文件合并成一个文件,若有设置Combiner,则也会使用Combiner来合并相同的key。 合并后的文件存放在本地磁盘中,而不是HDFS上。

  5)copy过程:简单地拉取数据。Reduce进程启动一些数据copy线程(Fetcher),通过HTTP方式请求map task的输出文件。因为map task早已结束,这些文件就归TaskTracker管理在本地磁盘中。 

  6)Merge阶段:合并不同map端copy来的数据。不断地merge后,最后会生成一个“最终文件”,此文件可能存在于磁盘上,也可能存在内存中。直接作为Reducer的输入。默认情况下,此文件是存放于磁盘中的。

(3)map任务个数的计算

  1)默认map个数:如果不进行任何设置,一个块就对应一个map任务:num = fileSize / blockSize;

  2)设置map个数:通过参数mapred.map.tasks来可以map个数,但此设置个数只有在大于(1)中num的时候,才会生效,goalNum = mapred.map.tasks;。

  3)设置处理文件大小: 可以通过mapred.min.split.size 设置每个task处理的文件大小,但是此设置大小只有在大于blockSize的时候才会生效。

    splitSize = max(mapred.min.split.size, block_size);

    splitNum = total_size / split_size;

  4)总结map个数的设置:

   a、如果想增加map个数,则设置mapred.map.tasks 为一个较大的值。

   b、如果想减小map个数,则设置mapred.min.split.size 为一个较大的值。

   c、如果输入中有很多小文件,依然想减少map个数,则需要将小文件merger为大文件,然后使用准则2。

(4)mapreduce中使用到的排序

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

(5)combiner函数解析

  1)为什么需要combiner函数:运行combiner函数在map端进行局部聚合操作,使map的输出结果更加紧凑,因此减少到写到磁盘上的数据和传递给reduce的数据

  2)conmbiner函数何时被使用:先是分区partition,然后根据hash(key)+partition排序,最后使用Combiner进行局部聚合;merger溢写文件时也会使用combiner函数合并相同的Key所对应的value。

  3)combiner为何不适用于求平均数:在求取平均数时,因为添加的Combiner组件是与reduce组件具有相同的逻辑,会提前求一次平均值后传给reduce类,导致求取的平均值错误。例如,求0、20、10、25和15的平均数,直接使用Reduce求平均数Average(0,20,10,25,15),得到的结果是14, 如果先使用Combiner分别对不同Mapper结果求平均数,Average(0,20,10)=10,Average(25,15)=20,再使用Reducer求平均数Average(10,20),得到的结果为15,很明显求平均数并不适合使用Combiner。

(6)mapreduce的优化

  1)数据的输入:合并小文件,在执行mr任务前将小文件进行合并,大量的小文件会产生大量的map任务。

  2)map阶段调优

   a、设置参数增大触发spill的内存上限,减少spill次数,从而减少磁盘IO。

   b、先进行combine处理,使数据更加紧凑,减少磁盘IO

   c、减少合并(merge)次数:增大merge的文件数目,减少merge的次数,从而缩短mr处理时间。

  3)reduce阶段

   a、合理设置map和reduce数:太少,会导致task等待,延长处理时间;太多,会导致 map、reduce任务间竞争资源,造成处理超时等错误。

   b、合理设置reduce端的buffer:默认情况下,数据达到一个阈值的时候,buffer中的数据就会写入磁盘,然后reduce会从磁盘中获得所有的数据。buffer和reduce是没有直接关联的,中间多个一个写磁盘->读磁盘的过程,既然如此可以通过参数来配置,使得buffer中的一部分数据可以直接输送到reduce,从而减少IO开销。mapred.job.reduce.input.buffer.percent,默认为0.0。当值大于0的时候,会保留指定比例的内存读buffer中的数据直接拿给reduce使用。

  4)数据倾斜

   a、自定义分区

   b、Combine:使用Combine可以大量地减小数据倾斜。

   c、采用Map Join,尽量避免Reduce Join

4、YARN

(1)yarn的介绍:

  MR和Spark作为YARN的应用运行在集群计算层和集群的存储层上的,Yarn整体上属于master/slave模型,主要依赖于三个组件来实现功能,分别是ResourceManager,ApplicationMaster,NodeManager。

  1)ResourceManager:管理集群上的资源,包括两部分调度器Scheduler,应用管理ApplicationManager。

   a、Scheduler负责各个运行中的应用的资源分配,受到资源容量,不负责应用程序的监控和状态追踪,而是基于应用程序的资源需求执行其调度功能,使用了叫做资源容器container的概念,container封装了某个节点上的多维度资源,如内存、CPU、磁盘、网络等,当AM向RM申请资源时,RM为AM返回的资源便是用Container表示的。YARN会为每个任务分配一个Container,且该任务只能使用该Container中描述的资源。

   b、ApplicationManager主要负责接收application的提交请求,为应用分配第一个Container来运行ApplicationMaster,还有就是负责监控ApplicationMaster,在遇到失败时重启ApplicationMaster运行的Container。

  2)NodeManager:主要负责与ResourceManager通信,负责启动和管理应用程序的container,监控container的资源使用情况(cpu和内存等),跟踪节点的监控状态,管理日志等。并报告给RM。

  3)ApplicationMaster:每个应用程序都有自己的ApplicationMaster,ApplicationMaster负责与scheduler协商合适的container,跟踪应用程序的状态。

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

(2) YARN的运行机制

  1)客户端提交application到ResourceManager并请求一个ApplicationMaster实例。

  2)ResourceManager找到一个可以运行Container的NodeManager,在这个Container中启动ApplicationMaster,并建立ApplicationMaster的RPC端口和用于跟踪的URL,用来监控application的状态。

  3)AM向RM进行注册后,ApplicationMaster向ResourceManager请求资源,ResourceManager根据资源调度策略尽可能最优的为AM分配container资源。

  4)Container被成功分配后AM向NodeManager发送信息启动Container,并在启动的Container中运行任务,并把任务运行的进度状态信息发送给AM。

  5)当所有任务完成之后,AM将所用到的Container归还给系统,并且注销。此时分布式应用执行结束。

(3)yarn的资源调度算法

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

  2)容量调度器(Capacity Scheduler):yarn中默认的调度器,通过为每个组织分配专门的队列,然后再为每个队列分配一定的集群资源,这样整个集群就可以通过设置多个队列的方式给多个组织提供服务了。除此之外,队列内部又可以垂直划分,这样一个组织内部的多个成员就可以共享这个队列资源了,在一个队列内部,资源的调度是采用的是先进先出(FIFO)策略。

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

(4)YARN的资源隔离方案

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

  ControlGroup:先对计算机的某个资源设置了一些限制规则,如只能使用 CPU 的20%。若我们想一些进程去遵守这个使用 CPU 资源的限制的话,就将它加入到这个规则所绑定的进程组中,之后,相应的限制就会对其生效。

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

5、Hadoop的高可用性。

(1)HDFS和MapReduce以及YARN单点故障解决方案:

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

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

(2)Hadoop中高可用的组件如下:

  1)SharedStorage共享存储系统:active master将信息写入共享存储系统,而standby master则读取该信息以保持与active master的同步,从而减少切换时间。

  2)ZKFailoverController:zkfc会周期性的向它监控的namenode(每个namenode各有一个zkfc)发生健康探测命令,来鉴定namenode是否处于正常工作状态,如果机器宕机,心跳失败,那么zkfc就会标记它处于不健康的状态;主要由两个核心组件构成:ActiveStandbyElector和HealthMonitor

   a、HealthMonitor负责监控各个活动master的状态,以根据它们状态进行状态切换。如主namenode磁盘空间不足。

   c、ActiveStandbyElector负责与zookeeper集群交互,通过尝试获取全局锁,以判断所管理的master进入active还是standby状态;

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

(3)常用的共享存储系统:zookeeper被YARN HA采用;HDFS被MapReduce HA采用;zookeeper,被HDFS HA采用。

(4)ZKFailoverController如何申请锁:

  若每个namenode是健康的,则每个NN所对应的zkfc会在zookeeper中保持一个打开的会话;对于active状态的namenode,其zkfc还会在zookeeper中占有一个短暂类型的znode,当主namenode挂掉时,其znode将会被删除,其ZKFailoverController跟主NameNode无法通信,此时主NN所对应的FailoverController就会把主NN宕机的信息汇报给Zookeeper,其它的ZKFailoverController便从ZK中得到了这条信息,然后它们给各自监控的NameNode发送切换指令。当其中一个备用namenode率先得到这把锁,即可升级为主namenode,同时标记状态为active,当宕机的namenode,重新启动,他会再次注册zookeeper,若发现已经有znode了,就自动变为standby状态,如此往复循环,保证高可靠性。

(5)主备namenode如何保持同步:两个NameNode为了数据同步,会通过一组称作JournalNodes的独立进程进行相互通信。当active状态的NameNode的命名空间有任何修改时,会告知大部分的JournalNodes进程。standby状态的NameNode有能力读取JNs中的变更信息,并且一直监控edit log的变化,把变化应用于自己的命名空间。standby可以确保在集群出错时,命名空间状态已经完全同步了。

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

  1)脑裂:脑裂是指在主备切换时,由于切换不彻底或其他原因,导致客户端和Slave误以为出现两个active master,最终使得整个集群处于混乱状态。

  2)解决脑裂问题,通常采用隔离(Fencing)机制,隔离要求:

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

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

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

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

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

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

6、总结知识点

(1)hadoop集群不用重启集群使配置生效及配置查询

  1)使用命令:hadoop dfsadmin -refreshNodes

  2)使用reconfigurable机制:提供一个ReconfigurationServlet工具,便于从web端变更配置。使用时将该servelt加入到相应节点的httpserver中,并在context中加入conf.servlet.reconfigurable.$P的参数,值为对应的Reconfigurable实现(一般为节点自身实现),其中$P表示的是ReconfigurationServlet在httpServer中对应的path。

   a、hadoop中Reconfigurable接口定义了可变配置的基本操作

   b、ReconfigurableBase,该基类有两个抽象方法,所有想要实现动态配置的节点,都需要实现这两个方法。

   c、ReconfigurationServlet 用于配置动态管理。

posted on 2020-03-28 17:20  hdc520  阅读(3314)  评论(0编辑  收藏  举报

导航