赞
踩
一、概述
HDFS是Hadoop生态下的分布式文件系统,基于Linux本地文件系统上的文件系统。
1.1 设计特点
1、大数据文件,非常适合上T级别的大文件或者一堆大数据文件的存储,如果文件只有几个G甚至更小就没啥意思了。
2、文件分块存储,HDFS会将一个完整的大文件平均分块存储到不同计算器上,它的意义在于读取文件时可以同时从多个主机取不同区块的文件,多主机读取比单主机读取效率要高得多得都。
3、流式数据访问,一次写入多次读写,这种模式跟传统文件不同,它不支持动态改变文件内容,而是要求让文件一次写入就不做变化,要变化也只能在文件末添加内容。
4、廉价硬件,HDFS可以应用在普通PC机上,这种机制能够让给一些公司用几十台廉价的计算机就可以撑起一个大数据集群。
5、硬件故障,HDFS认为所有计算机都可能会出问题,为了防止某个主机失效读取不到该主机的块文件,它将同一个文件块副本分配到其它某几个主机上,如果其中一台主机失效,可以迅速找另一块副本取文件。
二、架构原理
2.1 架构图
2.2 组件
1、块(Block):将一个文件进行分块,通常是64M。写入后不能修改,但是可以追加。
2、名称节点(NameNode):保存整个文件系统的目录信息、文件信息及分块信息,如果主 NameNode 失效,切换到Secondary NameNode。
3、数据节点(DataNode):分布在廉价的计算机上,用于存储Block块文件。
4、客户端(Client):通过与 NameNode和DataNode 交互访问HDFS中的文件。
其中,DataNode和NameNode是HDFS的两大核心。
三、名称节点(NameNode)
NameNode管理文件系统的命名空间,它维护着文件系统树及整棵树内所有的文件和目录,即元数据(MetaData)。元数据有三种存储方式:内存元数据,目的是提升性能,定期从磁盘加载一份镜像到内存中。
命名空间镜像文件(fsImage),保存整个文件系统的目录树。
编辑日志文件(edits),记录文件系统元数据发生的所有更改,如文件的删除或添加等操作信息。
如果NameNode不可用,那么等同于整个HDFS文件系统不可用。如果NameNode由于故障导致磁盘数据丢失,那么等同于整个HDFS文件系统数据丢失。如果NameNode块映射关系的内存爆满,那么等同于整个HDFS文件系统无法再继续存储,也就是意味着NameNode内存决定了HDFS能够存储的块数量。根据经验值,每个文件、目录和数据块的存储信息大约占 150 字节。
3.1 高可用
为了保证读写数据一致性,HDFS集群设计为只能有一个状态为Active的NameNode,但这种设计存在单点故障问题,官方提供了两种解决方案:QJM(推荐):通过同步编辑事务日志的方式备份命名空间数据,同时需要DataNode向所有NameNode上报块列表信息。还可以配置ZKFC组件实现故障自动转移。
NFS:将需要持久化的数据写入本地磁盘的同时写入一个远程挂载的网络文件系统做为备份。
通过增加一个Secondary NameNode节点,处于Standby的状态,与Active的NameNode同时运行。当Active的节点出现故障时,切换到Secondary节点。
为了保证Secondary节点能够随时顶替上去,Standby节点需要定时同步Active节点的事务日志来更新本地的文件系统目录树信息,同时DataNode需要配置所有NameNode的位置,并向所有状态的NameNode发送块列表信息和心跳。
同步事务日志来更新目录树由JournalNode的守护进程来完成,简称为QJM,一个NameNode对应一个QJM进程,当Active节点执行任何命名空间文件目录树修改时,它会将修改记录持久化到大多数QJM中,Standby节点从QJM中监听并读取编辑事务日志内容,并将编辑日志应用到自己的命名空间。发生故障转移时,Standby节点将确保在将自身提升为Active状态之前,从QJM读取所有编辑内容。
注意,QJM只是实现了数据的备份,当Active节点发送故障时,需要手工提升Standby节点为Active节点。如果要实现NameNode故障自动转移,则需要配套ZKFC组件来实现,ZKFC也是独立运行的一个守护进程,基于zookeeper来实现选举和自动故障转移。
3.2 数据合并
1、NameNode初始化时会产生一个edits文件和一个fsimage文件。
2、随着edits文件不断增大,当达到设定的阀值时,Secondary NameNode把edits文件和fsImage文件复制到本地,同时NameNode会产生一个新的edits文件替换掉旧的edits文件,这样以保证数据不会出现冗余。
3、Secondary NameNode拿到这两个文件后,会在内存中进行合并成一个fsImage.ckpt的文件(这个过程称为checkpoint),合并完成后,再将fsImage.ckpt文件复制到NameNode下。
4、NameNode文件拿到fsImage.ckpt文件后,会将旧的fsimage文件替换掉,并且改名成fsimage文件。
通过以上几步则完成了edits和fsimage文件的合并,依此不断循环,从而到达保证元数据的正确性。
3.3 HDFS联邦(Federation)
虽然HDFS HA解决了“单点故障”问题,但是在系统扩展性、整体性能和隔离性方面仍然存在问题。
(1)系统扩展性方面,元数据存储在NN内存中,受内存上限的制约。
(2)整体性能方面,吞吐量受单个NN的影响。
(3)隔离性方面,一个程序可能会影响其他运行的程序,如一个程序消耗过多资源导致其他程序无法顺利运行。
HDFS HA本质上还是单名称节点。HDFS联邦可以解决以上三个方面问题。
在HDFS联邦中,设计了多个相互独立的NN,使得HDFS的命名服务能够水平扩展,这些NN分别进行各自命名空间和块的管理,不需要彼此协调。每个DN要向集群中所有的NN注册,并周期性的发送心跳信息和块信息,报告自己的状态。
HDFS联邦拥有多个独立的命名空间,其中,每一个命名空间管理属于自己的一组块,这些属于同一个命名空间的块组成一个“块池”。每个DN会为多个块池提供块的存储,块池中的各个块实际上是存储在不同DN中的。
四、数据节点(DataNode)
DataNode角色的节点是真正存放块(block)数据的节点,当DataNode启动时,它将扫描其本地文件系统,生成与每个本地文件相对应的所有HDFS数据块的列表,并将此报告发送到NameNode。该报告称为BlockReport。
4.1 块副本(Replication)
每一个文件可以配置副本数量,默认是3,副本的作用是防止因某个DataNode挂掉或磁盘损坏而导致数据丢失,除此之外块副本还可以提高块可读取的节点,提高mapreduce计算任务向数据移动的概率。
因为同一个DataNode放置相同的块数据是没有意义的,所以NameNode不允许DataNode具有同一块的多个副本,即副本数量配置不能大于DataNode节点的数量。
每个文件可以在写入时指定这个文件块的副本数量,也可以在未来修改某个文件的块副本数量,文件块的副本数量配置作为块元数据的一部分保存在NameNode中。
4.2 放置策略
由于NameNode可以获取每个DataNode所属的机架ID,并且块副本数量配置信息保存在NameNode中,所以块的副本放置策略是由NameNode决定好返回给客户端的。
副本放置策略简单总结为:三分之一的副本位于写入器所在的节点上。
三分之二的副本位于写入器所在的同一个机架上。
其余三分之一则平均分布在其余机架上。
如果副本数大于3个,则随机确定其它的副本位置,一般副本数量配置为3个是比较理想的。
当修改某个文件的块副本数量时,NameNode将重新根据策略复制或减少块副本。当某个DataNode超过一定的时间(默认10分钟)没有上报心跳给NameNode,NameNode将认为该DataNode不可用,将不会分配块写入到这个DataNode中,原来分配在这个DataNode的块副本将会重新在其它可用的DataNode上复制。
4.3 磁盘平衡器
DataNode 将数据块存储到本地文件系统目录中,具体的目录可以通过配置 hdfs-site.xml 里面的 dfs.datanode.data.dir 参数。在典型的安装配置中,一般都会配置多个目录,并且把这些目录分别配置到不同的设备上,比如分别配置到不同的HDD(HDD的全称是Hard Disk Drive)和SSD(全称Solid State Drives,就是我们熟悉的固态硬盘)上。
当往HDFS上写入新的数据块时,DataNode 将会使用volume选择策略来为这个块选择存储的位置。目前Hadoop支持两种volume选择策略:round-robin 和 available space(详情参见:HDFS-1804),我们可以通过 dfs.datanode.fsdataset.volume.choosing.policy 参数来设置。
循环(round-robin)策略将新块均匀分布在可用磁盘上,而可用空间( available-space )策略优先将数据写入具有最大可用空间的磁盘(按百分比计算)。如下图:
默认情况下,DataNode 是使用基于round-robin策略来写入新数据块。然而在一个长时间运行的集群中,由于大规模文件删除或者通过往 DataNode 中添加新的磁盘会导致不同磁盘存储的数据很不均衡。即使你使用的是基于可用空间的策略,卷(volume)不平衡仍可导致较低效率的磁盘I/O。比如所有新增的数据块都会往新增的磁盘上写,在此期间,其他的磁盘会处于空闲状态,这样新的磁盘将会是整个系统的瓶颈。
DiskBalancer是一个命令行工具,可以在DataNode的所有磁盘上均匀分配数据。此工具与Balancer不同, 后者负责集群范围的数据平衡。由于多种原因,数据在节点上的磁盘之间可能存在不均匀的扩散。这可能是由于大量写入和删除或由于磁盘更换造成的。此工具针对给定的DataNode运行,并将块从一个磁盘移动到另一个磁盘。
五、数据读写
5.1 写流程
1、HDFS客户端提交写操作到NameNode上,NameNode收到客户端提交的请求后,会先判断此客户端在此目录下是否有写权限,如果有,然后进行查看,看哪几个DataNode适合存放,再给客户端返回存放数据块的节点信息,即告诉客户端可以把文件存放到相关的DataNode节点下。
2、客户端拿到数据存放节点位置信息后,会和对应的DataNode节点进行直接交互,进行数据写入,由于数据块具有副本replication,在数据写入时采用的方式是先写第一个副本,写完后再从第一个副本的节点将数据拷贝到其它节点,依次类推,直到所有副本都写完了,才算数据成功写入到HDFS上,副本写入采用的是串行,每个副本写的过程中都会逐级向上反馈写进度,以保证实时知道副本的写入情况。
3、随着所有副本写完后,客户端会收到数据节点反馈回来的一个成功状态,成功结束后,关闭与数据节点交互的通道,并反馈状态给NameNode,告诉NameNode文件已成功写入到对应的DataNode。
5.2 读流程
1、HDFS客户端提交读操作到NameNode上,NameNode收到客户端提交的请求后,会先判断此客户端在此目录下是否有读权限,如果有,则给客户端返回存放数据块的节点信息,即告诉客户端可以到相关的DataNode节点下去读取数据块;
2、客户端拿到块位置信息后,会去和相关的DataNode直接构建读取通道,读取数据块,当所有数据块都读取完成后关闭通道,并给NameNode返回状态信息,告诉NameNode已经读取完毕。
六、参考
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。