一、架构原理
HDFS 是Hadoop Distributed File System的简称,是HADOOP抽象文件系统的一种实现。Hadoop抽象文件系统可以与本地系统、Amazon S3等集成,甚至可以通过Web协议(webhsfs)来操作。
HDFS是由一个NAMENODE与多个DATANODE构成,如下图。
其中NAMENODE负责管理分布式文件系统的命名空间(Namespace)。
DATANODE 数据节点,用来具体的存储文件,维护了blockId 与 datanode本地文件的映射。
换个理解方法就是MASTER WORKER 模式,其中NAMENODE 对应是master,进所有datanode的datanode mate 信息的关联以及监控等相关事情。而DATANODE只负责存储数据。
HDFS基础知识思维导图如下:
二、写文件过程
- Client 调用 DistributedFileSystem 对象的 create 方法,创建一个文件输出流(FSDataOutputStream)对象;
- 通过 DistributedFileSystem 对象与集群的 NameNode 进行一次 RPC 远程调用,在 HDFS 的 Namespace 中创建一个文件条目(Entry),此时该条目没有任何的 Block,NameNode 会返回该数据每个块需要拷贝的 DataNode 地址信息;
- 通过 FSDataOutputStream 对象,开始向 DataNode 写入数据,数据首先被写入 FSDataOutputStream 对象内部的数据队列中,数据队列由 DataStreamer 使用,它通过选择合适的 DataNode 列表来存储副本,从而要求 NameNode 分配新的 block;
- DataStreamer 将数据包以流式传输的方式传输到分配的第一个 DataNode 中,该数据流将数据包存储到第一个 DataNode 中并将其转发到第二个 DataNode 中,接着第二个 DataNode 节点会将数据包转发到第三个 DataNode 节点;
- DataNode 确认数据传输完成,最后由第一个 DataNode 通知 client 数据写入成功;
- 完成向文件写入数据,Client 在文件输出流(FSDataOutputStream)对象上调用 close 方法,完成文件写入;
- 调用 DistributedFileSystem 对象的 complete 方法,通知 NameNode 文件写入成功,NameNode 会将相关结果记录到 editlog 中。
三、读文件过程
- Client 通过 DistributedFileSystem 对象与集群的 NameNode 进行一次 RPC 远程调用,获取文件 block 位置信息;
- NameNode 返回存储的每个块的 DataNode 列表;
- Client 将连接到列表中最近的 DataNode;
- Client 开始从 DataNode 并行读取数据;
- 一旦 Client 获得了所有必须的 block,它就会将这些 block 组合起来形成一个文件。
四、问题
1、数据错误,hdfs是怎么解决的呢?
原因
解决办法:在客户端读取到数据后,会采用MD5和sha1对数据块进行校验,以确定读取到正确的数据。
具体流程:
- 在文件被创建的时候,客户端对文件进行摘录,并把这些信息写入数据的同一路径隐藏文件中。
- 当客户端读取文件的时候,会先读取该信息文件,然后利用该信息文件对每个读取的数据块进行校验,如果校验出错,客户端就会请求到另外一个数据接地那读取该文件快,并且向NAMENODE报告这个文件块有错误,NAMENODE会定期检查并且重新复制这个块。
2、数据节点出错
DATANODE 难免会造成不可用
解决思路主要是通过心跳的方式
解决流程:
- 每个数据节点会定期向NAMEnode 节点发送心跳,向namenode报告自己的状态。
- 当数据节点发生故障或者网络发生断网时,namenode节点就无法收到来自以下数据节点的心跳信息。这些数据节点就会被标记为宕机,节点上面的所有数据都会标记为不可读,namenode不会再给他们发送任何的IO请求。
- 这时,有可能出现一种情况,由于一些数据节点的不可用,会导致一些数据块的副本量小于冗余因子。
- namenode 会定期检查这些数据情况,一旦发现某些数据块的副本数量小于冗余因子,就会启动数据冗余复制,为它生产新的副本。
- HDFS和其他分布式文件系统最大的区别就是可以调整冗余数据的位置。
3、namenode 节点出错(单点故障问题)
namenode节点保存了所有的元数据信息,其中最核心的两大数据结构是FsImage 合Editlog,如果这两个文件发生了损坏,那么整个HDFS实例降 失效。
因此,HDFS设置了备份机制,把这些核心文件同步复制到备份服务器SecondaryNameNode上。当namenode出错时,就可以根据备份服务器SecondaryNameNode中的FsImage和Editlog数据进行恢复。
4、小文件问题以及DATANODE水平扩展极限问题
Hadoop中每个目录、文件和block都会以对象的形式保存在NameNode的内存中。根据经验每个对象在内存中大概占用150个字节。HDFS中保存2000万个文件,每个文件都在同一个文件夹中,而且每个文件都只有一个block,则NameNode需要6GB内存。
小文件问题:
1、当NameNode重启时,它都需要从本地磁盘读取每个文件的元数据,意味着你要读取300GB数据到内存中,不可避免导致NameNode启动时间较长。
2、一般来说,NameNode会不断跟踪并检查每个数据块的存储位置。这是通过DataNode的定时心跳上报其数据块来实现的。数据节点需要上报的block越多,则也会消耗越多的网络带宽/时延。即使节点之间是高速网络(万兆/光纤),但不可避免的会带来一些不好的影响。
3、NameNode本身使用300G内存,相当于JVM你需要配置300GB的heap,对于JVM来说本来就存在稳定性的风险,比如GC时间较长。
另外大量小文件意味着大量的随机磁盘IO,磁盘IO通常是MapReduce性能的最大瓶颈之一,在HDFS中对于相同数量的数据,一次大的顺序读取往往优于几次随机读取的性能。
5、HDFS为什么是128M这么大的一个数据块呢?
在文件系统中,系统存储文件时,需要定位该数据在磁盘中的位置,再进行传输处理。
定位在磁盘的位置需要时间,同样文件传输也是需要时间的。
T(存储时间)=T(定位时间)+T(传输时间)
如果每个要传输的块设置得足够大,那么从磁盘传输数据的时间可以明显大于定位这个块开始位置的时间。
假如文件太小,在namenode 的映射列表就会非常大,影响寻址时间,寻址时间如果大于传输时间,就没有意义了。
但如果block 设置过太大,在MapReduce 任务中,Map或者Reduce任务的个数小于集群机器数量,会使得作业运行效率很低。
6、namenode还存在哪些问题以及怎么解决?
存在问题:
- 单点故障问题
- 不可以水平扩展(是否可以通过纵向扩展来解决?)
- 系统整体性能受限于单个名称节点的吞吐量
- 单个名称节点难以提供不同程序之间的隔离性
解决方案
热备份 (HDFS HA)
HDFS HA(High Availability)是为了解决单点故障问题
HA集群设置两个名称节点,“活跃(Active)”和“待命(Standby)”
两种名称节点的状态同步,可以借助于一个共享存储系统来实现
一旦活跃名称节点出现故障,就可以立即切换到待命名称节点
Zookeeper确保一个名称节点在对外服务
名称节点维护映射信息,数据节点同时向两个名称节点汇报信息
存在的问题就有可能出现脑裂的问题。
Federation
多个命名空间。为了处理一个namenode的局限性,搞了几个namanode大家一起来管理。就像编程中的命名空间一样
在HDFS Federation中,设计了多个相互独立的名称节点,使得HDFS的命名服务能够水平扩展,这些名称节点分别进行各自命名空间和块的管理,相互之间是联盟(Federation)关系,不需要彼此协调。并且向后兼容
HDFS Federation中,所有名称节点会共享底层的数据节点存储资源,数据节点向所有名称节点汇报
属于同一个命名空间的块构成一个“块池
HDFS Federation设计可解决单名称节点存在的以下几个问题:
1. HDFS集群扩展性。多个名称节点各自分管一部分目录,使得一个集群可以扩展到更多节点,不再像HDFS1.0中那样由于内存的限制制约文件存储数目
2. 性能更高效。多个名称节点管理不同的数据,且同时对外提供服务,将为用户提供更高的读写吞吐率
3. 良好的隔离性。用户可根据需要将不同业务数据交由不同名称节点管理,这样不同业务之间影响很小