HDFS介绍:
HDFS源于Google三篇论文(GFS,Mapreduce,BigTable)中的GFS理论启发而诞生的基于海量数据分布式存储的一种文件系统,HDFS也是Hadoop生态圈最重要的组件之一,他解决了传统数据库对非结构化数据的存储问题,和海量数据存储的问题,一次写入多次读取,是目前大数据存储地位最高的分布式存储文件系统。
HDFS的组件:
Client端:客户段主要是向hdfs发起读取或者写入命令,与NameNode和DataNode交互。
NameNode:NameNode是hdfs集群中的Master地位,重要性不言而喻,也是众多DateNode小劳动们不可动摇的领导地位,主要职责有三
1:负责与Client端进行通信
2:维护hdfs的文件系统命名空间(可以对比你的window系统的我的电脑,里面有cdef盘,每个盘里有大量的文件夹即目录,每个目录下有很多文件,某一时间的快照就是该命名空间),维护着文件系统目录树和整棵树内的文件和目录,这些信息以两种文件形式永久的保存在本地磁盘,1:命名空间镜像文件(fsimage)和编辑日志文件(editlog)
3:通过心跳机制接收DataNode对自身状况的报告,和文件存储问题和状况的报告,以便NameNode及时更新元数据信息
1:负责与Client端通信,执行Client端的写入或者读取文件命令
2:数据真正存储的地方
3:通过心跳机制,三秒一次向NameNode汇报自身状况,包括文件块存储位置等
SecondaryNameNode:也称辅助NameNode,一般也是个单独的节点,减轻NameNode工作压力的组件,负责FSimage和editslog文件的合并,副本容错策略和SecondaryNameNode都是hdfs高可靠的一种体现。
下图是官方hdfs架构图:
HDFS工作原理:
RPC调用:即一种远程过程调用,调用远程节点的方法,就像调用自己本地方法一样,要求调用的方法名是一样的,而且必须实现RPC通信协议。比如我在client端调用open()读文件方法,可以通过RPC调用到NameNode节点的open()方法。
namenode存储的元数据:每个文件的信息都存储在一个Namenode对象中:文件名name,副本数num,block块id;然后DataNode通过心跳机制向namenode汇报的信息有 数据块,机架位置,机架那几个节点存储了这个数据块,大家可以根据官方这个图理解一下
读文件:
1:Clent端向NameNode发送读文件请求,通过调用SysTem类的open()方法来打开希望读取的文件,System对于hdfs来说是DistributeFileSystem的一个子类,
2:DistributeFileSystem通过RPC远程调用NameNode,通过调用NameNode的getBlockLocations()方法,获取文件起始块的位置信息,对于每个文件块,NameNode返回改文件块的副本的DateNode存储你位置,NameNode通过sortLocationBlocks()方法,根据他们与客户端的网络位置进行排序(涉及到机架感知和网络拓扑知识点),如果客户端本事就是一个DateNode,并且本地磁盘保存了相应数据块的一个副本时,该节点将从本地磁盘直接读取数据。
3:DistributeFileSystem类返回了一个FSDataInputStream对象,FSDataInputStream对象是一个支持文件定位的输入流,FSDataInputStream封装了一个DFSInputStream类,DFSInputStream类负责管理NameNode与DataNode的I/O。接着,客户段对这个IO流调用read()方法。
4:存储着文件起始块的DataNode地址的DFSInputStream随即连接最近距离的第一个DataNode(第二步通过排序确定了位置),通过反复调用read()方法读取文件到客户端。
5:当第一个数据块读取到末端时,DFSInputStream关闭与该DateNode的连接,通过询问NameNode获取下一批文件块的datenode地址。
6:文件读取完成,Client客户端就对FSDataInputStream调用close()方法,结束文件的读取,在读取过程中,如果DFSInputstream与Datanode通信出错,DFSInputstream就会连接该数据块的第一个DataNode(与client端距离第二近)进行读取,并且会记住这个错误的DataNode,将信息发送给NameNode,以便NameNode及时分配新的DataNode来存储错误节点上的副本,并且更新元数据信息,DFSInputstream在读取DataNode上数据块时,也会通过校验和来判断该数据是否完整是否被损坏。
写文件:
1:和读文件类似,Cleint端通过DistributeFileSystem类调用create()方法来创建文件,Distributefilesystem通过RPC调用NameNode的create()方法,在文件系统的命名空间创建一个新的文件,此时该文件不含有任何数据,NameNode要对该文件做一系列检查通过调用complete方法,确保Hdfs上此文件之前不存在,并且Client客户段对该文件具有操作的权限,否则将抛出IO异常信息。
2:DistributeFileSystem向客户段返回一个FSDataOutputStream对象,类似读文件时,FSDataOutputStream封装了一个DFSOutputStream对象,DFSOutputStream负责DataNode和NameNode的通信,在客户端写入数据的时候,DFSOutputStream对象将数据分成一个个数据包,并且将数据包存储在一个数据队列DataQueue中。
3:DataStreamer负责处理这个数据队列,它根据DataNode列表要求NameNode分配适合的新数据块来存储数据备份,这一组DateNode构成了一个管线,假设我们的副本有三个,那么三个DataNode构成了一个管线,dataStreamer将数据包流式的传输到管线中的第一个DataNode,然后有该DataNode向第二个DataNode传递数据包副本,再由第二个DataNode向第三个DataNode传递副本。
4:DFSOutputStream也维护一个确认队列,当所有的DataNode都发送了确认信息,该数据包才会从数据队列中删除,如果在数据写入的期间,DataNode发生故障,首先关闭管线,然后把队列中的任何数据包都添加会数据队列中,寻找正常的合适的其他DataNode节点并且给该节点做一个标识,将标识通知给namenode,以便在恢复故障DataNode之后,可以删除存储的数据块,然后在正常的DataNode中 重新传递数据。
5:客户段完成数据的写入后,调用close()方法。
SecondaryNameNode工作机制和安全模式
HDFS是一个高可用高可靠的分布式文件存储系统,他的高可靠一体现在副本策略二体现在SecondaryNameNode上,其次心跳机制
FSimage文件和editlog文件,FSimage文件是HDFS的命名空间镜像文件,一般持久化到NameNode的本地磁盘上,但是当Nodenode启动时,通常会把它也在内存中加载一份,Editlog主要记录着用户对HDFS的操作,随着editlog越来越大,namenode承受的压力也越来越大,而且namenode本来工作性质和工作量意味着namenode的重要性,如果将FSImage和ditlog合并的工作留给namenode,会加大这位领导的压力,万一累坏了宕机了可就麻烦了,于是设计了一个领导的小助理ScondaryNameNode,帮助领导来处理合并这两个文件的压力。
触发FSimage和editlog合并的checkpoint有两个默认条件(可以通过配置文件调整):1.空间上editlog的大小达到了64M 2:时间上达到了3600秒
触发检查点之后,原edit文件停止写入,创建一个新的editlog文件,以提供客户端后面的请求操作的写入,小助理SecondaryNameNode通过http协议的get方法,将editlog文件和FSImage文件拉倒自己的节点上,进行两个文件的合并成新的FSImage,之后通过put方法,将合并后的FSImage文件放到NameNode上,将原来领导的FSImage文件替换掉。
当namenode重新启动之后,一般会进入一个只允许读不允许写的安全模式,因为检查点的触发是需要条件的,所以editlog文件合并到FSImage文件中,具有延时性,所以当冲洗年启动namenode之后,要完成之前没有合并的操作,所以会进入安全模式,但是namenodeformat格式化之后重启namenode不会进入,是因为此时系统中editlog文件是空的 并不需要合并。