Hadoop HDFS详解
一、HDFS名词解释
1.Block: 在HDFS中,每个文件都是采用的分块的方式存储,每个block放在不同的datanode上(副本策略),每个block的标识是一个三元组(block id, numBytes,generationStamp),其中block id是具有唯一性,具体分配是由namenode节点设置,
然后再由datanode上建立block文件,同时建立对应block meta文件
2.Packet:在DFSclient(分布式文件系统客户端)与DataNode之间通信的过程中,发送和接受数据过程都是以一个packet为基础的方式进行
3.Chunk:中文名字也可以称为块,但是为了与block区分,还是称之为chunk。在DFSClient与DataNode之间通信的过程中,由于文件采用的是基于块的方式来进行的,但是在发送数据的过程中是以packet的方式来进行的,每个packet包含了多个chunk,
同时对于每个chunk进行checksum计算,生成checksum bytes
小结:
1.一个文件被拆成多个block持续化存储(block size 由配置文件参数决定)
2.数据通讯过程中一个 block 被拆成 多个 packet
3.一个 packet 包含多个 chunk
详解Packet:
*Packet结构与定义: Packet分为两类,一类是实际数据包,另一类是heatbeat包。一个Packet数据包的组成结构如下图所示:
*图中Header属性信息如图:
*Data部分:
*Data部分是一个Packet的实际数据部分,主要包括一个4字节校验和(Checksum)与一个Chunk data部分,Chunk data部分最大为512字节
*在构建一个Packet的过程中,首先将字节流数据写入一个buffer缓冲区中,也就是从偏移量为25的位置(checksumStart)开始写Packet数据Chunk的Checksum部分,从偏移量为533的位置(dataStart)开始写Packet数据的Chunk Data部分,
直到一个Packet创建完成为止。
*当写一个文件的最后一个Block的最后一个Packet时,如果一个Packet的大小未能达到最大长度,也就是上图对应的缓冲区中,Checksum与Chunk Data之间还保留了一段未被写过的缓冲区位置,在发送这个Packet之前,会检查Chunksum与
Chunk Data之间的缓冲区是否为空白缓冲区(gap),如果有则将Chunk Data部分向前移动,使得Chunk Data 1与Chunk Checksum N相邻,然后才会被发送到DataNode节点
二、HDFS架构
1.架构图
2.分析架构图:
*HDFS Client: 系统使用者,调用HDFS API操作文件;与NN交互获取文件元数据;与DN交互进行数据读写。【注意】写数据时文件切分由Client完成
*Namenode:Master节点(也称元数据节点),是系统唯一的管理者。负责元数据的管理(名称空间和数据块映射信息);配置副本策略;处理客户端请求
*Datanode:数据存储节点(也称Slave节点),存储实际的数据;执行数据块的读写;汇报存储信息给NN
*Secondary NameNode:小弟角色,分担大哥namenode的工作量;是NameNode的冷备份;合并fsimage和fsedits然后再发给namenode。【注意】在hadoop 2.x 版本,当启用 hdfs ha 时,将没有这一角色。
备份说明:
*热备份:b是a的热备份,如果a坏掉。那么b马上运行代替a的工作
*冷备份:b是a的冷备份,如果a坏掉。那么b不能马上代替a工作。但是b上存储a的一些信息,减少a坏掉之后的损失
3.hdfs构架原则
*元数据与数据分离:文件本身的属性(即元数据)与文件所持有的数据分离
*主/从架构:一个HDFS集群是由一个NameNode和一定数目的DataNode组成
*一次写入多次读取:HDFS中的文件在任何时间只能有一个Writer。当文件被创建,接着写入数据,最后,一旦文件被关闭,就不能再修改。
*移动计算比移动数据更划算:数据运算,越靠近数据,执行运算的性能就越好,由于hdfs数据分布在不同机器上,要让网络的消耗最低,并提高系统的吞吐量,最佳方式是将运算的执行移到离它要处理的数据更近的地方,而不是移动数据
三、NameNode
1.NameNode是整个文件系统的管理节点,也是HDFS中最复杂的一个实体,它维护着HDFS文件系统中最重要的两个关系:
*HDFS文件系统中的文件目录树,以及文件的数据块索引,即每个文件对应的数据块列表
*目录树、元数据和数据块的索引信息会持久化到物理存储中,实现是保存在命名空间的镜像fsimage和编辑日志edits中。【注意】在fsimage中,并没有记录每一个block对应到哪几个Datanodes的对应表信息
*数据块和数据节点的对应关系,即某一块数据块保存在哪些数据节点的信息
*在NameNode启动后,每个Datanode对本地磁盘进行扫描,将本Datanode上保存的block信息汇报给Namenode,Namenode在接收到每个Datanode的块信息汇报后,将接收到的块信息,以及其所在的Datanode信息等保存在内存中。
HDFS就是通过这种块信息汇报的方式来完成 block -> Datanodes list的对应表构建
*fsimage记录了自最后一次检查点之前HDFS文件系统中所有目录和文件的序列化信息;
*edits是元数据操作日志(记录每次保存fsimage之后到下次保存之间的所有hdfs操作)
*在NameNode启动时候,会先将fsimage中的文件系统元数据信息加载到内存,然后根据eidts中的记录将内存中的元数据同步至最新状态,将这个新版本的 FsImage 从内存中保存到本地磁盘上,然后删除旧的 Editlog,这个过程称为一个检查点 (checkpoint)
*为了避免edits日志过大,在Hadoop1.X中,SecondaryNameNode会按照时间阈值(比如24小时)或者edits大小阈值(比如1G),周期性的将fsimage和edits的合并,然后将最新的fsimage推送给NameNode。
而在Hadoop2.X中,这个动作是由Standby NameNode来完成.
*由此可看出,这两个文件一旦损坏或丢失,将导致整个HDFS文件系统不可用。
*Hadoop2.x做高可用,把fsimage与edits文件保存在JNS。
*Hadoop1.x高可用的做法就是将dfs.namenode.name.dir设置成以逗号分隔的多个目录,这多个目录至少不要在一块磁盘上,最好放在不同的机器上,比如:挂载一个共享文件系统
*安全模式
Namenode 启动后会进入一个称为安全模式的特殊状态。处于安全模式 的 Namenode 是不会进行数据块的复制的。 Namenode 从所有的 Datanode 接收心跳信号和块状态报告。块状态报告包括了某个 Datanode 所有的数据 块列表。
每个数据块都有一个指定的最小副本数。当 Namenode 检测确认某 个数据块的副本数目达到这个最小值,那么该数据块就会被认为是副本安全 (safely replicated) 的;在一定百分比(这个参数可配置)的数据块被 Namenode 检
测确认是安全之后(加上一个额外的 30 秒等待时间), Namenode 将退出安全模式状态。接下来它会确定还有哪些数据块的副本没 有达到指定数目,并将这些数据块复制到其他 Datanode 上。
四、Secondary NameNode(在HA cluster中又称为standby node)
流程图
分析:namenode 响应 Secondary namenode 请求,将 edit log 、fsimage推送给 Secondary namenode , namenode开始重新写一个新的 edit log,Secondary namenode 收到来自 namenode 的 fsimage 文件和 edit log,合并两者并
将新的 fsimage 推送给 Namenode,Namenode 用新的 fsimage 取代旧的 fsimage 。在 fstime 文件中记下检查 点发生的时间!
五、HDFS写文件
*流程图
*下述分析需要参照上述链接:
*Client将FileA按64M分块。分成两块,block1和Block2;(注意:Hadoop2.x分块默认大小是128M,64M是Hadoop1.x的默认block size)
*Client向nameNode发送写数据请求,如图蓝色虚线①------>
*NameNode节点,记录block信息。并返回可用的DataNode,如粉色虚线②--------->
Block1: host2,host1,host3
Block2: host7,host8,host4
*client向DataNode发送block1;发送过程是以流式写入,流式写入过程如下:【注意】具体的写数据步骤还是由客户端实现的
将64M的block1/block2按64k的packet划分
client--packet-->host2-->host1-->host3
client--packet-->host7-->host8-->host4(副本默认3个)
host2,host1,host3(host7,host8,host4)向NameNode,host2(host7)向Client发送通知,说“消息发送完了”。如图粉红颜色实线所示
client收到host2(host7)发来的消息后,向namenode发送消息,说我写完了。这样就真完成了。如图黄色粗实线
*小结:
*写入的过程,按hdsf默认设置,1T文件,我们需要3T的存储,3T的网络流量
*在执行读或写的过程中,NameNode和DataNode通过HeartBeat进行保存通信,确定DataNode活着。如果发现DataNode死掉了,就将死掉的DataNode上的数据,放到其他节点去。读取时,要读其他节点去
*挂掉一个节点,没关系,还有其他节点可以备份;甚至,挂掉某一个机架,也没关系;其他机架上,也有备份(尽量不要把所有的副本放到一个机架上,一般我们把副本放在两个机架上,不会太分散!)
六、HDFS读文件
*流程图
*分析:
*客户端通过调用FileSystem对象的open()方法来打开希望读取的文件,对于HDFS来说,这个对象是分布文件系统的一个实例;
*DistributedFileSystem通过使用RPC来调用NameNode以确定文件起始块的位置,同一Block按照重复数会返回多个位置,这些位置按照Hadoop集群拓扑结构排序,距离客户端近的排在前面
*前两步会返回一个FSDataInputStream对象,该对象会被封装成DFSInputStream对象,DFSInputStream可以方便的管理datanode和namenode数据流,客户端对这个输入流调用read()方法
*存储着文件起始块的DataNode地址的DFSInputStream随即连接距离最近的DataNode,通过对数据流反复调用read()方法,将数据从DataNode传输到客户端
*到达块的末端时,DFSInputStream会关闭与该DataNode的连接,然后寻找下一个块的最佳DataNode,这些操作对客户端来说是透明的,客户端的角度看来只是读一个持续不断的流
*一旦客户端完成读取,就对FSDataInputStream调用close()方法关闭文件读取