HDFS

当数据集的大小超过一台独立的物理计算机的存储能力时,有必要对它进行分区并存储到若干单独的计算机上。分布式文件系统:管理网络中跨多台计算机存储的文件系统。

HDFS:Hadoop Distribued Filesystem。

1.1 HDFS的设计

以流式数据访问模式来存储超大文件,

流式数据访问:数据集通常由数据源生成或者从数据源复制而来,而后在数据集上进行各种分析。每次分析都会涉及数据集的大部分数据,因此读取整个数据集的时间延迟比读取第一条记录的时间延迟更重要。

低时间延迟的数据访问:如几十毫秒范围的低时间延迟数据访问应用不适合在HDFS上运行

大量小文件:namenode将文件系统的元数据存储在内存中,因此该文件系统所能存储的文件总数受限于namenode的文件总量,因此存储小文件会使namenode的存储效率降低。

多文件写入,任意修改文件:HDFS的文件写入只支持单个写入者,且写操作总是以'只添加'方式在文件末尾写数据。不支持多写入者,不支持在文件的任意位置进行修改。

1.2 HDFS的概念

1.2.1 数据块(block)

默认128MB,HDFS上的文件也被划分为多个分块作为独立的存储单元。HDFS块较大的目的是最小化寻址开销。

优点:1.文件可大于任一磁盘容量,文件的块不需要存在同一个磁盘上,。2.简化了存储子系统的设计,文件的元数据如权限信息等,不需要与块一同存储,可以在其它系统单独管理这些元数据。3.数据备份的数据容错能力。

fsck指令可显示块信息

% hdfs fsck / -files -blocks

1.2.2 namenode和datanode

HDFS有两类节点以管理节点-工作节点模式运行,即一个namenode和多个datanode。namenode管理文件系统的命名空间,维护文件系统树及整棵树内的所有文件与目录,也记录着每个文件中各个块所在的数据节点信息。

客户端通过与namenode和datanode的交互来访问整个文件系统。如果运行namenode的服务的机器毁坏,文件系统上所有的文件将会丢失。
因此提供两种方法来提供namenode的容错。1.备份组成文件系统元数据持久状态的文件,即同时写入一个远程挂载的网络文件系统。2.运行一个辅助namenode,定期合并编辑日志与命名空间镜像,防止编辑日志过大。

1.2.3 块缓存

访问频繁的文件,把对应的块显式的缓存在datanode的内存中,以堆外块缓存的形式存在。

1.2.4 联邦HDFS

每个namenode管理文件系统命名空间中的一部分,每个namenode维护一个命名空间卷,有命名空间的元数据和block pool组成,block pool包含该命名空间下的的文件的所有数据块,且命名空间卷之间互相独立
namenode直接相互独立,各自分工管理自己的区域,且不需要互相协调,一个namenode挂掉了不会影响其他的namenode。

1.2.5 HDFS的高可用性

hadoop系统无法提供服务直到有新的namenode上线,因为namenode是唯一存储元数据与文件到数据块映射的地方。

为达到不会出现明显中断的目的,需要修改架构如下:1.datanode需要同时向两个或多个namenode发送数据块处理报告。2.namenode之间通过高可用共享存储实现编辑日志的共享,备用namenode接管工作后,将通读共享编辑日志直至末尾以实现状态同步。3.备用namenode为活动namenode命名空间设置周期性检查点。

QJM:提供一个高可用的编辑日志而设计,以一组日志节点的形式运行,每次编辑必须写入多个日志节点。由于最新状态存在内存中,因此备用节点可以实现快速任务接管。

1.2.5.1 故障切换与规避

故障转移控制器:将活动namenode转移为备用namenode,每个namenode上都运行一个轻量级的,用于监视是否失效,当然也可手动发起故障转移。

规避:确保先前活动的namenode不会执行危害系统并导致系统崩溃的操作。同一时间QJM只允许一个namenode向编辑日志中写入数据,因此可用SSH规避命令杀死namenode的进程。

1.3 命令行接口

文件系统的基本操作

#本地复制文件去HDFS
#可省略hdfs://localhost,因为已在core-site.xml中指定了
#也可使用相对路径
hadoop fs -copyFromLocal /filePath/filename hdfs://localhost/targetPath/filename

#文件复制回本地并检查是否一致
hadoop fs -copyToLocal filename filenameCopy(Local)
md5 filename(local原) filenameCopy
hadoop fs -mkdir dirname
hadoop fs -ls

文件访问权限:只读(r)、写入(w)、可执行(x)

1.4 Hadoop文件系统

Java抽象类org.apache.hadooplfs.FileSystem定义了Hadoop中的一个文件系统的客户接口,且有具体实现。见Hadoop权威指南p52 表3.1

接口

通过Java API可以调用大部分Hadoop文件系统的交互操作。
1.HTTP
Http接口比原生的Java客户端要慢,因此不到万不得已不要用其传输特大数据。

通过HTTP来访问HDFS有两种方法:

1.直接访问(HDFS守护进程直接服务于来自客户端的HTTP请求)

操作都先被发送给namenode,再以流方式传给datanode

2.通过代理(一个或多个)访问(Client->HDFS Proxy:HTTP request,HDFS Proxy->Namenode:RPCrequest,HDFSProxy->Datanode:block request)

通常都通过代理服务器,实现不同数据中心中部署的Hadoop集群之间的数据传输,或从外部网络访问云端的Hadoop集群。

1.5 Java接口

FileSystem API

使用FileSystem API打开文件的输入流,HDFS通过Hadoop Path对象来代表文件,将路径视为一个Hadoop文件系统URL。

public static FileSystem get(Configuration conf) throws IOException
public static FileSystem get(URI uri,Configuration conf) throws IOException
public static FileSystem get(URI uri,Configuration conf,String user) throws IOException

Configuration封装了客户端服务器的配置,通过设置配置文件读取类路径实现(etc/hadoop/core-site.xml),第一个方法返回的core-site.xml的默认文件系统,第二个给定URI,第三个指定用户

文件读取(InputStream):有了FileSystem后通过open获取文件的输入流,FileSystem的open方法返回的是FSDataInputStream,其有seek和getPos方法,

IOUtils.copyBytes(in,System.out,4096,true)

写入数据(OutputStream ):指定一个Path对象并返回一个写入的流FSDataOutputStream,

IOUtils.copyBytes(in,out,4096,true)

列出文件

FileSystem的getFileStatus用于获取文件或目录的FileStatus对象,FileStatus封装了文件和目录的元数据(文件长度、块大小、复本、修改时间、所有者和权限信息)

删除

FileSystem.delete永久性的删除文件或目录

1.6 数据流

并行复制

hadoop distcp file1 file2将文件复制到另一个文件中去

hadoop distcp dir1 dir2 将dir1的内容全部复制到dir2下(-overwrite覆盖全部 OR -update仅更新 )