HDFS分布式文件系统
HDFS基本知识
前言
1. 分布式文件系统是Hadoop两大核心组成部分之一,提供了在廉价服务器集群中进行大规模分布式文件存储的能力。HDFS是Google的GFS的开源实现。
2. HDFS具有很好的容错能力,并且兼容廉价的硬件设备,因此可以以较低的成本利用现有机器实现大流量和大数据量的读写。
3. 分布式文件系统在物理结构上由计算机集群中多个节点构成。节点分为两部分:
- “主节点”:Master Node 或 “名称节点”:NameNode;
- ”从节点”:Slave Node 或 “数据节点”:DataNode;
4. NameNode和DataNode之间的交互是通过RPC进行的。RPC(Remote Procedure Call Protocol)是远程调用协议,其对底层网络协议是透明的,跨越了传输层和应用层,是Hadoop是最重要的底层核心协议之一。
目标
HDFS在设计上要实现以下目标:
-
1)兼容廉价的硬件设备
-
2)流数据读写:为了提高数据吞吐率,以流式方式来访问文件系统数据
-
3)大数据集
-
4)简单的文件模型:采用“一次写入,多次读取”模型,文件一旦完成写入,关闭后就无法再次写入,只能被读取。
-
5)强大的跨平台兼容性
局限性
-
1)不适合低延迟数据访问:对于低延时要求的应用,HBase更好
-
2)无法高效存储大量小文件:名称节点来管理文件系统元数据时,元数据会被保存在内存中使客户端可以快速获取,访问大量小文件时影响性能
-
3)不支持多用户写入及任意修改文件。
HDFS相关概念
块(Block)
- 默认一个块大小是64MB,在HDFS中的文件会被拆分成多个块,每个块作为独立的单元进行存储。HDFS在文件块大小设置上要远远大于普通文件系统,以期在处理大规模文件时能得到更好的性能。但是,通常MapReduce中的Map任务一次只处理一个块中的数据,如果启动的任务太少会降低作业并行处理速度,所以块的大小设置也不易过大。
HDFS架构
名称节点(NameNode)
-
名称节点主要负责文件和目录的创建,删除和重命名等,同时管理着数据节点和文件块的映射关系。因此客户端只有访问名称节点才能找到请求的文件块所在的位置,进而到相应位置读取所需文件块。
-
同时,名称节点还负责管理分布式文件系统的命名空间,保存了两个核心的数据结构,即FsImage(元数据镜像文件)和EditLog(日志文件)。FsImage用于维护文件系统树以及文件树中所有文件和文件夹的元数据(文件的名称,位置,副本数,拥有者,组,权限,存储块,各块在哪些节点上)。操作日志文件EditLog中记录了所有针对文件的创建,删除,重命名等操作。
名称节点启动时,会将FsImage的内容加载到内存中,然后执行EditLog中的各项操作,使得内存中的元数据保持最新,操作完成后,会创建新的FsImage文件和一个空的EditLog。
数据节点(DataNode)
-
数据节点负责数据的存储和读取。在存储时,由名称节点分配存储位置,然后由客户端把数据直接写入相应数据节点;在读取时,客户端从名称节点获得数据节点和文件块的映射关系,从而找到相应位置访问文件块。数据节点还要根据名称节点的命令创建,删除数据块和冗余复制。
-
每个数据节点会周期性向名称节点发送"心跳"信息,报告自己的状态,没有按时发送心跳信息的节点会被标记为"宕机",不会给他分配任何I/O请求。
第二名称节点(Secondary NameNode)
- 在设计中,HDFS采用第二名称节点"Secondary NameNode",以解决实际操作中EditLog逐渐变大的问题。
功能:
- 首先,可完成EditLog和FsImage的合并操作,减小EditLog文件大小,缩短名称节点重启时间;
- 其次,作为名称节点的"检查点",保存名称节点的元数据信息,起到"冷备份"的作用。
体系结构图示
HDFS核心设计
Block大小设置
前文我们有提到,在这里不进行过分的赘述。
HDFS存储原理
-
1.数据的冗余存储
HDFS采用了多副本方式对数据进行冗余存储,通常一个数据块的多个副本会被分布到不同数据节点上。可加快数据传输速度,容易检查数据错误,保证数据可靠性。 -
2.数据副本存取策略(机架感知:就近写入,就近读取)
HDFS默认的冗余复制因子是3,每一个文件块会被同时保存到3个地方。其中,两份副本在同一机架的不同机器上,第三个副本放在不同机架的机器上面。
数据复制(流水线)
- 当客户端向HDFS文件写数据的时候,一开始是写入本地的临时文件,假设该文件的复制因子是3,那么客户端会从NameNode获取一张DataNode列表来存放副本。然后客户端再向第一个DataNode传输数据,第一个DadaNode会一小部分一小部分(4KB)地接受数据,将每个部分写入本地仓库,同时传输给第二个DataNode。其他节点也是这样,边接受边传输,直到最后一个副本节点,只接受并存储。
HDFS 数据读写(使用Java API)
读文件
1.调用java.net.URL(简单粗暴法)
- (1)调用java.net.URL类获得输入流
- (2)通过IOUtils操作输入流对文件读取
static {
URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory());
//识别URL路径
}
InputStream in = new URL("hdfs://bigdata-hadoop.wbc.com/user/wbc/datas/").openStream();
//do something for in
IOUtils.closeStream(in);
2.调用FileSystem类
- (1)实例化FileSystem对象
在FileSystem类中有两种静态方法可以获得FileSystem类对象
1. public static FileSystem get(Configuration conf)
//默认加载core-site.xml,并返回默认文件系统。
2. public static FileSystem get(URI uri, Configuration conf)
//根据传入的完整的URI来确定返回的文件系统类型。根据传入的完整的URI来确定返回的文件系统类型。
- (2)通过.open()方法打开文件,DistributedFileSystem会创建输入流FSDataInputStream对象(两种)。
对于HDFS而言,具体的输入流就是DFSInputStream。