1.HDFS写数据流程
1) 客户端调用 DistribuedFileSystem 的 Create() 方法来创建文件。
2) DistributedFileSystem 用 RPC 连接 NameNode,请求在文件系统的命名空间中创建一个新的文件;NameNode 首先确定文件原来不存在,并且客户端有创建文件的权限,然后创建新文件;DistributedFileSystem 返回 FSOutputStream 给客户端用于写数据。
3) 客户端调用 FSOutputStream 的 Write() 函数,向对应的文件写入数据。
4) 当客户端开始写入文件时,FSOutputStream 会将文件切分成多个分包(Packet),并写入其內部的数据队列。FSOutputStream 向 NameNode 申请用来保存文件和副本数据块的若干个 DataNode,这些 DataNode 形成一个数据流管道。
队列中的分包被打包成数据包,发往数据流管道中的第一个 DataNode。第一个 DataNode 将数据包发送给第二个 DataNode,第二个 DataNode 将数据包发送到第三个 DataNode。这样,数据包会流经管道上的各个 DataNode。
5) 为了保证所有 DataNode 的数据都是准确的,接收到数据的 DataNode 要向发送者发送确认包(ACK Packet)。确认包沿着数据流管道反向而上,从数据流管道依次经过各个 DataNode,并最终发往客户端。当客户端收到应答时,它将对应的分包从内部队列中移除。
6) 不断执行第 (3)~(5)步,直到数据全部写完。
7) 调用 FSOutputStream 的 Close() 方法,将所有的数据块写入数据流管道中的数据结点,并等待确认返回成功。最后通过 NameNode 完成写入。
2.HDFS读数据流程
- 客户端调用 DistributedFileSystem 的 Open() 方法打开文件。
- DistributedFileSystem 用 RPC 连接到 NameNode,请求获取文件的数据块的信息;NameNode 返回文件的部分或者全部数据块列表;对于每个数据块,NameNode 都会返回该数据块副本的 DataNode 地址;DistributedFileSystem 返回 FSDataInputStream 给客户端,用来读取数据。
- 客户端调用 FSDataInputStream 的 Read() 方法开始读取数据。
- FSInputStream 连接保存此文件第一个数据块的最近的 DataNode,并以数据流的形式读取数据;客户端多次调用 Read(),直到到达数据块结束位置。
- FSInputStream连接保存此文件下一个数据块的最近的 DataNode,并读取数据。
- 当客户端读取完所有数据块的数据后,调用 FSDataInputStream 的 Close() 方法。
3.HDFS小文件解决方案
- Hadoop Archive- 一个高效地将小文件放入HDFS块中的文件存档工具,它能够将多个小文件打包成一个HAR文件,这样就减少了NameNode的内存使用。
- Sequence File- Sequence File由一系列的二进制key/value组成,如果key为文件名,value为文件内容,则可以将大批小文件合并成一个大文件。
- CombineFilelnputFormat- CombineFileInputFormat是一种新的InputFormat,用于将多个文件合并成一个单独的Split,另外,它会考虑数据的存储位置。
- 开启JVM重用- 对于大量小文件Job,可以开启JVM重用会减少45%运行时间。- JVM重用原理:一个Map运行在一个JVM上,开启重用的话,该Map在JVM上运行完毕后,JVM继续运行其他Map。具体设置: mapreduce.job.jvmnumtasks值在10-20之间
4.Yarn工作机制
当用户向 YARN 中提交一个应用程序后,YARN 将分两个阶段运行该应用程序 :第一个阶段是启动 ApplicationMaster ;第二个阶段是由 ApplicationMaster 创建应用程序,为它申请资源,并监控它的整个运行过程,直到运行完成。
步骤:
- 1.用户 YARN中提交应用程序, 其中包括MRAppMaster程序、 启动 MRAppMaster 的命令、用户程序等。(MRAppMstr 程序在客户端生成,这一步已经将应用程序先行程序提交到RM的Application Manager模块进行处理,将运行程序所需的jar包、环境变量、切片信息等提交到HDFS之上,需要等MRAPPMstr返回一个可用的Container的时候在节点提交执行。可以理解为惰性处理,减少资源占用,做到需要什么提交什么)
- 2.ResourceManager 为该应用程序分配第一个 Container,并与对应的 Node-Manager 通信,要求它在这个 Container 中启动应用程序的MRAppMaster。(APPMaster就是先头兵,这时的操作是RM的ApplicationManager来进行处理)
- 3.MRAppMaster 首先向 ResourceManager 注册, 这样用户可以直接通过ResourceManage 查看应用程序的运行状态,然后它将为各个任务申请资源,并监控它的运行状态,直到整个应用运行结束。
- 4.MRAppMaster 采用轮询的方式通过 RPC 协议向 ResourceManager 申请和领取资源。
- 5.一旦 MRAppMaster 申请到资源后,便与对应的 NodeManager 通信,要求它启动任务。(理解集群中不同节点的资源动态变动,可用Container以及不同的Task可以在不同的节点运行)
- 6.NodeManager 为任务设置好运行环境(包括环境变量、JAR 包、二进制程序 等)后,将任务启动命令写到一个脚本中,并通过运行该脚本启动任务。(此时,客户端才真正上传具体Task需要的Jar包等等运行资源,同时NodeManager通过调用资源运行对应的Task任务);
- 7.各个任务通过某个RP 协议向MRAppMaster 汇报自己的状态和进度,以让 MRApplicationMaster 随时掌握各个任务的运行状态,从而可以在任务失败时重新启动任务。 在应用程序运行过程中,用户可随时通过 RPC 向 MRAppMaster 查询应用程序的当 前运行状态。
- 步骤4~7是重复执行的
- 8.应用程序运行完成后,MRAppMaster 向 ResourceManager 注销并关闭自己。
版权归原作者 独影月下酌酒 所有, 如有侵权,请联系我们删除。