Hadoop基础知识 主要内容: 一:Hadoop核心简介:hdfs,yarn,mapreduce 二:Hafs: shell操作,hdfs体系结构,hdfs 的Java调用 三:Mapreduce: mapreduce 原理应用及部分源码分析和实例代码 四:Hadoop环境搭建:为分布集群搭建,HA集群,联盟环境搭建
一:Hadoop 2.0的核心 如下图 1. HDFS 分布式文件系统 主从结构 主节点,可以有2个: namenode 从节点,有很多个: datanode namenode负责: 接收用户操作请求,是用户操作的入口 维护文件系统的目录结构,称作命名空间 datanode负责: 存储文件 2. Yarn 资源的调度和管理平台 主从结构 主节点,可以有2个: ResourceManager 从节点,有很多个: NodeManager ResourceManager负责 集群资源的分配与调度例如cpu 内存 MapReduce、Storm、Spark等应用,必须实现ApplicationMaster接口,才能被RM管理 NodeManager 负责 单节点资源的管理 3. MapReduce 依赖磁盘io的批处理计算模型 主从结构 主节点,只有一个:MRAppMaster MRAppMaster负责: 接收客户提交的计算任务 把计算任务分给NodeManager中的Container执行,即任务调度 监控Task的执行情况
二:Hdfs Hdfs的体系结构如图 Namenode :整个文件系统的管理节点,维护着整个文件系统的文件目录树, 文件目录的元信息和每个文件对应的数据块列表。接收用户的操作请求。 如下图在name/current目录下有文件:edits 和 fsimage ① fsimage:元数据镜像文件。存储某一时段NameNode内存元数据信息。 ② edits:操作日志文件。(SecondaryNamenode 的作用是将edits的日志记录信息向fsimage合并,当Hadoop集群启动时datanode的存储信息会被namenode记录。这样namenode就起管理整个文件的作用了。当有两个namenode其中一个是备用。只有一个是启动状态,一个死机时就可以将fsimage的内容给备用的namenode从而可以继续使用hadoop) ③ BERSION:存放命名空间Id,集群ID,block块ID等信息
Datanode :存储文件的数据,按块存储block,hadoop2之后一个Block是128M,不足128M的文件按照一个块存在datanode中。Replication副本数,默认是3.所以假如某存储某个文件的某个block的节点挂掉,可以使用副本。存储时也应该主要给副本留空间,假如设置副本数3,一个100M的节点只能存储100M的三分之一大小的文件。
HDFS shell命令 通过命令对hadoop进行操作,基本用法和linux命令操作差不多 只是在前面添加hdfs dfs –ls / 可以通过hdfs dfs (回车)查看
Hdfs Java操作 • 写文件 create 类似hdfs dfs –put 命令 • 读取文件 open 类似hdfs dfs –get 命令 • 删除文件delete 类似hdfs dfs –rm 命令 • 创建目录 mkdirs • 删除文件或目录 delete • 列出目录的内容 listStatus • 显示文件系统的目录和文件的元数据信息 getFileStatus • 显示文件存储位置getFileBlockLocations 例子:读取文件 FileSystem fileSystem = getFileSystem(); FSDataInputStreamopenStream = fileSystem.open(new Path("hdfs://IP地址:9000/aaa")); IOUtils.copyBytes(openStream,System.out, 1024, false); IOUtils.closeStream(openStream); 读文件过程 客户端(client)用FileSystem的open()函数打开文件 DistributedFileSystem用RPC调用名称节点,得到文件的数据块信息。 对于每一个数据块,名称节点返回保存数据块的数据节点的地址。 DistributedFileSystem返回FSDataInputStream给客户端,用来读取数据。 客户端调用stream的read()函数开始读取数据。 DFSInputStream连接保存此文件第一个数据块的最近的数据节点。 Data从数据节点读到客户端(client) 当此数据块读取完毕时,DFSInputStream关闭和此数据节点的连接,然后连接此文件下一个数据块的最近的数据节点。 当客户端读取完毕数据的时候,调用FSDataInputStream的close函数。 在读取数据的过程中,如果客户端在与数据节点通信出现错误,则尝试连接包含此数据块的下一个数据节点。 失败的数据节点将被记录,以后不再连接。
RCP 远程调用协议,通过网络从远程计算机程序上请求服务。Rcp跨越了传输层和应用层,使开发包括网络分布多线程的应用程序更加容易。 RPC调用 是cs结构,是在不同jvm之间调用java方法。 HDFS的rpc调用 ClientProtocol是DFSClient与NameNode通讯的。用户代码是通过DistributedFileSystem调用DFSClient与NameNode通讯。 DataNodeProtocol是DataNode与NameNode通讯的。 NameNodeProtocl是SecondaryNameNode与NameNode通讯的。 Hadoop整个体系结构就是构建在rcp之上。心跳原理。
Hdfs读写文件原理 (从网上看到的例子感觉很详细。) 读:如上图 1.首先调用FileSystem对象的open方法,其实是一个DistributedFileSystem的实例 2.DistributedFileSystem通过rpc获得文件的第一个block的locations,同一block按照副本数会返回多个locations,这些locations按照hadoop拓扑结构排序,距离客户端近的排在前面. 3.前两步会返回一个FSDataInputStream对象,该对象会被封装成DFSInputStream对象,DFSInputStream可以方便的管理datanode和namenode数据流。客户端调用read方法,DFSInputStream最会找出离客户端最近的datanode并连接。 4.数据从datanode源源不断的流向客户端。 5.如果第一块的数据读完了,就会关闭指向第一块的datanode连接,接着读取下一块。这些操作对客户端来说是透明的,客户端的角度看来只是读一个持续不断的流。 6.如果第一批block都读完了,DFSInputStream就会去namenode拿下一批blocks的location,然后继续读,如果所有的块都读完,这时就会关闭掉所有的流。 如果在读数据的时候,DFSInputStream和datanode的通讯发生异常,就会尝试正在读的block的排第二近的datanode,并且会记录哪个datanode发生错误,剩余的blocks读的时候就会直接跳过该datanode。DFSInputStream也会检查block数据校验和,如果发现一个坏的block,就会先报告到namenode节点,然后DFSInputStream在其他的datanode上读该block的镜像 该设计的方向就是客户端直接连接datanode来检索数据并且namenode来负责为每一个block提供最优的datanode,namenode仅仅处理block location的请求,这些信息都加载在namenode的内存中,hdfs通过datanode集群可以承受大量客户端的并发访问。
写:如上图 1.客户端通过调用DistributedFileSystem的create方法创建新文件 2.DistributedFileSystem通过RPC调用namenode去创建一个没有blocks关联的新文件,创建前,namenode会做各种校验,比如文件是否存在,客户端有无权限去创建等。如果校验通过,namenode就会记录下新文件,否则就会抛出IO异常. 3.前两步结束后会返回FSDataOutputStream的对象,象读文件的时候相似,FSDataOutputStream被封装成DFSOutputStream.DFSOutputStream可以协调namenode和datanode。客户端开始写数据到DFSOutputStream,DFSOutputStream会把数据切成一个个小packet,然后排成队列dataquene。 4.DataStreamer会去处理接受dataqueue,他先问询namenode这个新的block最适合存储的在哪几个datanode里,比如副本数是3,那么就找到3个最适合的datanode,把他们排成一个pipeline.DataStreamer把packet按队列输出到管道的第一个datanode中,第一个datanode又把packet输出到第二个datanode中,以此类推。 5.DFSOutputStream还有一个对列叫ackqueue,也是有packet组成,等待datanode的收到响应,当pipeline中的所有datanode都表示已经收到的时候,这时akc queue才会把对应的packet包移除掉。 如果在写的过程中某个datanode发生错误,会采取以下几步:1) pipeline被关闭掉;2)为了防止丢包ack queue里的packet会同步到data queue里;3)把产生错误的datanode上当前在写但未完成的block删掉;4)block剩下的部分被写到剩下的两个正常的datanode中;5)namenode找到另外的datanode去创建这个块的复制。当然,这些操作对客户端来说是无感知的。 6.客户端完成写数据后调用close方法关闭写入流 7.DataStreamer把剩余得包都刷到pipeline里然后等待ack信息,收到最后一个ack后,通知datanode把文件标示为已完成。 另外要注意得一点,客户端执行write操作后,写完得block才是可见的,正在写的block对客户端是不可见的,只有调用sync方法,客户端才确保该文件被写操作已经全部完成,当客户端调用close方法时会默认调用sync方法。是否需要手动调用取决你根据程序需要在数据健壮性和吞吐率之间的权衡。
|