大数据面试准备-hadoop篇

Hadoop组成

  主要包括三部分;HDFS分布式文件存储,mapreduce分布式计算引擎,yarn资源调度框架

HDFS的读写流程

       HDFS写流程

  1. Client客户端发送上传请求,通过RPC与NameNode建立通信,NameNode检查改用户是否有上传权限,以及上传的文件是都在HDFS对应的目录重名,如果,两者中任意一个不满足,则直接报错,如果都满足,则返回一个客户端可以上传的信息
  2. Client根据文件大小进行切分,默认是128m一块,切分完成之后给NameNod发送请求上传第一个block块上传到那台服务器上
  3. NameNode收到请求之后,根据网络拓扑和机架感知以及副本机制进行文件分配,返回可用的DataNode的地址
  4. 客户端收到地址之后与服务器地址列表中的A进行通信,本质上就是RPC调用,建立通道,A收到请求后会继续调用B,B在调用C,将整个通道建立完成,逐渐返回Client
  5. Client开始向A上发送第一个block(先从磁盘读取数据然后放在本地内存缓存,以packet(数据包 64kb)为单位,A收到一个packet就会发送给B,然后B发送给C,A每上传一个packet就会放入一个应答队列等待应答)
  6. 数据被分割成一个个的packet数据包在通道上依次传输,在通道反向传输中,逐个发送ack(命令正确应答),最终由通道的第一个DataNode节点将A将通道发送给Client.
  7. 当第一个block传输之后,Client再次请求NameNode上传第二个block,NameNode重新选择三台DataNode给Client。

    注意:hadoop在设计的时候考虑到数据的安全与高效,数据文件默认在HDFS上存放三份,存储策略为本地文件一份,同机架内的其他节点放一份,不同机架的其他节点放一份

        HDFS读数据流程

  1. Client向NameNode发送RPC请求,,请求文件block的位置
  2.   NameNode收到请求之后会检查用户权限以及是否有这个文件,如果都符合,则会视情况返回部分或者全部的block列表,对于每个block,NameNode都会返回改block副本的 DataNode地址;返回这些的DataNode地址。会按照集群拓扑结构的出DataNode与客户端的距离,然后进行排序,排序的两个规则:网络拓扑结构中距离Client近的距离;心跳机制中超时汇报的DataNode状态为STALE。这样的排靠后
  3. Client在选择排序靠前的 DataNode来读取block,如果客户端本身就是DataNode,那么将从本地直接获取数据(短数据读取特性)   
  4. 底层上本质是建立Socket Stream(FSDataInputStream) ,重复调用父类的Data的read方法,直到在这个块上的数据读取完毕
  5. 当读取完列表的block后,若文件还没有结束,客户端会继续向NameNode获取下一批的block列表
  6. 读取完一个block都会进行checksum验证,如果读取DataNode时出现错误,客户端会通知NameNode,然后再从一个用户block副本的DataNode继续读
  7. read方法是并行读取block信息,不是一块一块的读取,NameNode只是返回Client请求包含块的DataNode地址,并不是返回请求块的数据
  8.  最终读取来所有的block会合并成一个完整的文件   

   2.HDFS在读取文件的时候,如果其中一个文件块突然坏了怎么办 

       客户端读取完DataNode上的块数据之后会进行checksum验证,也就是把客户端读取的数据与本地的块HDFS上的原始块进行校验,如果发现校验结果不一致,客户端会通知NameNode,然后再从下一个拥有该块副本的DataNode继续读

   3.HDFS上产文件的时候,如果其中一个DataNode突然挂掉了怎么办

  客户端上传文件时与DataNode建立pipeline管道,管道的正方向是客户端向DataNode发送的数据包,管道的反方向是DataNode像客户端发送的ack确认,也就是一个正确接收到数据后发送一个已确认应接收的应答,当DataNode突然挂掉之后,客户端就接收不到这个DataNode发送的ack确认,客户端就会通知NameNode,NameNode检查该块的副本与规定的不符,NameNode会通知DataNode去复制副本,并将挂掉的DataNode做下线处理,不再让他参与文件的上传与下载

   4.NameNode在启动的时候会做哪些操作

    NameNode数据存储在内存和本地磁盘,本地磁盘数据存储在fsimage镜像文件和edits编辑日志文件

首次启动NameNode:

  1.  格式化文件系统,为了生成fsimage镜像文件
  2. 启动NameNode
    1. 读取fsimage文件,将文件内容加载到内存
    2. 等待DataNode注册与发送block report
  3. 启动DataNode:
    1. 向NameNode注册
    2. 发送block report
    3. 检查fsimage中记录的块数量和block report中的块的总数是否相同
  4. 对文件系统进行操作(创建目录,上传文件,删除文件等)
    1. 此时内存中已经有文件系统改变的信息,但是磁盘中没有文件系统改变的信息,此时会将这些改变信息写入edits文件中,edits文件中存储的是文件西戎元数据改变的信息

第二次启动NameNode:

  1. 读取fsimage和edits文件
  2. 将fsimage和edits文件合并成新的fsimage文件
  3. 创建新的edits文件,开始内容为空
  4. 启动DataNode

5.Secondary NameNode 的工作机制

 secondary NameNode是合并NameNode的simage和edits文件到fsimage文件

具体的工作机制

  1.  secondary NameNode询问NameNode是否需要checkpoint,直接返回NameNode是否的检查结果
  2. secondary NameNode请求执行checkpoint
  3. NameNode滚动正在写的edits日志
  4. 将滚动前的编辑日志和镜像文件拷贝到 secondary NameNode
  5.  secondary NameNode加载编辑日志跟镜像文件到内存,并合并
  6. 生成新的镜像文件fsimage.chkpoint
  7. fsimage.chkpoint拷贝到NameNode
  8. NameNode将fsimage.chkpoint重新命名fsimage

       如果NameNode中的元数据丢失,是可以从secondary NameNode恢复一部分元数据信息,但不是全部,因为NameNode正在写的edits日志还没有拷贝econdary NameNode,这部分数据是没办法恢复的

6.

6.Secondary NameNode不能恢复 NameNode的全部数据,如何保证NameNode的数据存储安全

  1. 元数据信息同步在HA方案中采用的是共享存储,每次写文件的时,需要将日志同步写入到共享存储,这个步骤成功才能认定文件成功,然后备份节点定期从共享存储同步日志,以便进行主备切换
  2. 监控NameNode状态采用zookeeper,两个NameNode节点的状态存放在zookeeper中,另外两个NameNode节点分别有一个进程监控程序,实时读取zookeeper中NameNode的状态,来判断当前的NameNode是不是已经down机。如果standy的NameNode节点的ZKFC发现主节点已经挂掉,那么强调给原本Active NameNode 节点发送强制关闭请求,之后将备用的NameNode设置为Active

7.NameNode HA中会出现脑裂问题吗 怎么解决脑裂

      假设NameNode1当前状态为Active状态,NameNode2当前状态为Standby状态,如果某一时刻NameNode1对应的ZKFailoverController进程发生了假死现象,那么Zookeeper服务端会认为NameNode1挂掉了,根前面的主备切换逻辑,NameNode2会替换NameNode1进入Active状态,但是此时NameNode1可能任然处理Active状态正常运行,这样NameNode1和NameNode2都处于active状态,都可以对外提供服务,这种情况称为脑裂。

脑裂对于NameNode这类数据一致性要求非常高的系统来说是灾难性的,数据安全会发生错乱,且无法恢复。zookeeper社区对于这种问题叫做fencing,中文翻译叫做隔离,想办法把旧的active NameNode隔离起来,使他不能正常对外提供服务

在进行fencing的时候,会执行以下的操作:

  1. 首先尝试调用这个旧的active NameNode的HAServiceProtocolRPC接口的transitionToStandby方法,看能不能把它的状态转换为Standby状态。
  2. 如果transitionToStandby方法调用失败,那么就执行Hadoop配置文件之中的预定义的隔离措施,Hadoop目前主要提供两种隔离措施,通常选择sshfence:
    • sshfence:通过SSH登录到目标机器上,执行命令fuser 将对应的进程杀死
    • shellfence :执行一个用户自定义的shell脚本来讲对应的进程隔离

8.小文件过多有什么危害,如何避免

Hadoop上大量的HDFS元数据信息存储在NameNode内存中,因此过多的小文件必然会压垮NameNode的内存。每个元数据对象约占150bye,如果1千万个小文件NameNode大约需要2G空间

一亿个小文件NameNode需要20G空间

需要在上传文件的时候合并小文件,,客户端上传时执行一定的策略先合并,使用Hadoop的combineFileputFormat<k,v>实现小文件的合并

9.HDFS的组织架构,

  • Client客户端:

    • 切分文件。文件上传HDFS的视乎,Client将文件切成一个一个的blo然后进行存储
    • 与NameNode交互,获取文件位置信息
    • 与DataNode交互,读取或写入数据
    • Client提供一些命令来管理HDFS,比如开启关闭HDFS,访问HDFS目录及内容
  • NameNode:名称节点,也称主节点,存储数据的元数据信息,不存储具体的数据
    • 管理HDFS的名称空间
    • 管理数据块的映射信息
    • 配置副本策略
    • 处理客户端读写请求
  • DataNode
    • 数据节点,也称从节点,NameNode下达命令,DataNode执行实际的操作
      • 存储实际的数据块
      • 执行数据块的读/写操作
  • Secondary NameNode :并非是NameNode的设备,当NameNode挂掉的时候,它并不能马上替换NameNode并提供服务
    • 辅助NameNode,分单其工作量
    • 定期合并FSimage,并推送给NameNode
    • 在紧急情况下,可以辅助恢复NameNode

10.MR中MapTask的工作机制

  • 简单概述:

    • inputfile通过split被分割成多个split文件,通过Record按行读取内容给map(自己写的处理方法逻辑的方法),数据被map处理完之后交给outputcollect收集器,对其结果的key进行分区,然后写入buffer,每个maptask都有一个内存缓存区(环形缓冲区),存放着map的输出结果,当缓冲区快要溢满的时候需要将缓冲区的文件以一个临时文件的方式溢写到磁盘,当整个maptask结束后再对整个磁盘中的这个maptask产生的所有临时文件进行合并,生产最终的输出文件,等待reducetask的拉取
  • 详细步骤

    1. 读取数据组件的inputformat默认是(Textinputformat)会通过getSplits方法对输入目录下的文件进行逻辑切片得到block,有多少个block对应需要启动多少个maptask
    2. 讲输入文件切分成为block之后,由RecordeReader对象(默认LineRecordeReader)进行读取,\n作为分隔符,读取一行数据,返回<k,v>,key表示每行字母的偏移值,value表示这一行的文本内容
    3. 读取block返回的<k,v>,进入用户自己继承的Mapper类中,执行用户重写的map函数,RecordReader读取一行就调用一次
    4. Mapper逻辑结束之后,将mapper的每条结果通过context.write进行collect数据收集。在collect中,会先对其进行分区处理,默认使用HashPartitioner,
    5. 接下来会将数据写入内存,内存中这片区域叫做环形缓冲区(默认是100mb),缓冲区的作用是批量收集Mapper结果,较少磁盘IO的影响,我们的key/value以及partition的结果都会被写入缓冲区,当然,在写之前,key与value的值都会被序列化成字节数组
    6. 当环形环形缓冲区的数据达到溢写比例(默认是0.8)也就是达到80m,溢写线程启动,需要对这80m空间的key做排序,排序是MapReduce模型的默认行为,这里的排序也是对序列化的字节做的排序
    7. 合并溢写文件,每次溢写会在磁盘上生成一个临时文件,如果mapper的输出结果真的很达,有多次这样的溢写发生,磁盘相应就会有多个临时文件存在,当整个数据处理结束之后开始对整个磁盘上的临时文件进行merge合并,最终只有一个文件写入磁盘,还会为最终的文件提供一个索引文件,以记录对个reduce对应数据的偏移量

11.MR中ReduceTask的工作机制

  • 简单描述

    • Reduce大致分为copy、sort、reduce三个阶段,重点在前两个阶段。

      • copy阶段包含一个eventFetcher来获取已完成的map列表,由Fetcher线程去copy数据,在此过程中会启动两个merge线程,分别为inmerotymerger和onmerotymerger,分别将内存中的数据merge到磁盘和将磁盘中的数据进行merge。待数据完成copy后,开始进行sort阶段,主要是执行finalmerge操作,纯粹的sort阶段,完成之后就是reduce阶段,调动用户自定义的reduce函数进行处理

  • 详细步骤

    • copy阶段:简单的拉取数据。Reduce进程启动一些数据copy线程,通过HTTP方式请求maptask获取属于自己的文件

    • merge阶段:在远程拷贝数据的同时,ReduceTask启动两个后台线程对内存和磁盘上的文件进行合并,以防止内存使用过多,或磁盘文件过多。
    • 合并排序,把分散的数据合并到一个大的数据后,还会在对合并后的数据进行排序
    • 对排序后的键值对调用reduce方法:键相等的键值对调用一次reduce方法,每次调用会产生零个或多个键值对,最后把这些文件写入到HDFS文件中

12.MR中Shuffle阶段

shuffle阶段分为四个步骤:依次为分区,排序,规约,分组,其中前面是三个步骤是在map阶段完成,最后一个在reduce阶段完成

shuffle是MapReduce的核心,它分布在MapReduce的map阶段和reduce阶段,一般是从map的输出开始到reduce取的数作为输入之前的过程称为shuffle

  1. Collect阶段:将maptask的结果输出到默认大小为100m的环形缓冲区,保存为的是key/value,partition分区信息等
  2. spilt阶段:当内存的中的数据量达到一定的阈值的时候,就会将数据写入本地磁盘,再将数据写入本地磁盘之前需要对数据进行一次排序,如果配置了combiner,还会将相同的分区号和key的数据进行排序
  3. maptask阶段的merge:把所有的溢出的临时文件进行一次合并操作,以确保一个maptask,最终只产生一个中间数据文件
  4. copy阶段:reducetask启动fetcher线程到已经完成的maptask的节点上复制一份属于自己的数据,这些数据默认会保存在内存的缓冲区中,当内存的缓冲区达到一定的阈值是,就会将数据写到磁盘上
  5. reducetask的merge阶段:reducetask远程复制数据的同时,会在后台开启两个线程对内存到本地的数据文件进行合并操作;
  6. sort阶段:在对数据进行合并的同时,会进行排序操作,由于maptask阶段已经对数据进行局部的排序,reducetask只需要copy的数据的最终整体有效性即可。

      shuffle中的缓冲区大小会影响到MapReduce程序的执行效率,原则上说,缓冲区越大,磁盘io的次数越少,执行速度就越快,缓冲区的大小可以通过参数调制,参数mapreduce.task.io.sprt.mb默认100m

13.shuffle阶段的数据压缩机制了解吗

 在shuffle阶段,可以看到数据通过大量的拷贝,从map阶段输出的数据,都要通过网络拷贝,发送到reduce阶段,这一过程,涉及到大量的网络io,如果数据能够进行压缩,那么发送的数据量就会少的多

14.在写MR时什么情况下可以使用规约

  规约(combiner)是不能够影响人物的运行结果的局部汇总,适用于求和类,不适用于求平均值,如果reduce的输入参数类型和输出参数类型是一样的则规约的类可以使用reduce类,只需要在驱动中指明规约的类即可

15.yarn集群的架构和工作原理

  yarn的基本涉及思想是将MapReduce V1中的jobtracker拆分为两个独立的服务:ResourceManager和ApplicationMaster负责整个系统的资源管理和分配,ApplicationMaster负责单个应用程序的管理 

    • ResourceManager:RM是一个全局的资源管理器,负责整个系统的资源管理和分配,它由两个部分组成调度器和应用程序管理

   调度器根据容量、队列等限制条件,将系统中的资源分配给正在运行的应用程序,在保证容量,公平性和服务等级的前提下,优化集群资源利用率,让所有的资源都得到充分的利用,应用管理程序负责管理整个系统中的所有应用程序,包括应用程序的提交,与调度器的协商资源以启动AApplicationMaster、监控ApplicationMaster的运行状态并在失败的时候重启

    • ApplicationMaster:主要工能有与RM调度器协商以获得资源,资源以container表示,将得到的任务进一步分配给内部任务,与NM通信以停止/启动任务,监控所有的内部任务状态,并在任务运行失败的时候重新为任务申请资源以重启任务
    • NodeManager:NodeManager是每个节点上的资源和任务管理器,一方面,它会定期的向RM汇报本节点上的资源利用情况和各个container的运行状态;另外一方面,他接收并处理来自AM的container启动和停止请求
    • container:是yarn中的资源抽象,封装了各种资源,一个应用程序会分配一个container,这个应用程序只能使用这个container中的描述资源,不同于MapReduce 中槽位的资源封装,container是一个动态资源的划分单位,更能充分利用资源

16.yarn的任务提交流程

  当jobclient想yarn提交一个应用程序后,yarn将会分两个阶段运行这个应用程序,一个是启动ApplicationMaster;第二个阶段是由ApplicationMaster创建应用程序,申请资源,监控运行直到结束,具体步骤如下

  1. 用户向yarn提交一个应用程序,并指定ApplicationMaster程序、启动ApplicationMaster的命令,用户程序
  2. RM为这个应用程序分配第一个container,并与之对应的NM通讯,要求它在这个container中启用应用程序ApplicationMaster
  3. ApplicationMaster向RM注册,然后拆分为内部各个子任务,为各个子任务申请资源,并监控这些任务的运行,直到结束
  4. AM采用轮询的方式向RM申请和领取资源
  5. RM为AM分配资源,以container形式返回
  6. AM申请到资源后为便与之对应的NM通讯,要求NM启动任务
  7. 为任务设置好运行环境,将任务命令启动写到一个脚本中,并通过脚本启动任务
  8. 各个人物向AM汇报自己的状态和进度,以便当任务失败时可以重启任务
  9. 应用程序完成后,ApplicationMaster想ResourceManager注销并关闭自己

17.yarn的资源调度模型

  FIFO Scheduler(先来先服务):实际上就是一个先进先出的队列,头上的应用程序先分配资源,后面的任务待头上的任务满足后在分配下一个

       Capacity Scheduler(容量调度器):针对小任务的一个调度器,会提前预占用一定的集群资源

       Fair Scheduler(公平调度器):第一个任务提交的时候获取集群的所有资源,第二个任务提交的时候会分配这个集群资源的一半资源

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2023-03-08 20:49  Valuez  阅读(18)  评论(0编辑  收藏  举报