Hadoop Distributed File System,简称HDFS,是一个分布式文件系统。
1. 特性:
1.1. 大数据集
运行在HDFS上的应用具有很大的数据集。可以是从GB到TB级的。
1.2. 高容错性
在hadoop集群环境下,每份数据都被保存在多个结点里边。一个结点的不可用不会导致该结点存储的数据不可用。
1.3. 高吞吐量
跑在Hdoop上的应用,更多的是做批处理,HDFS的设计中更多的考虑到了数据批处理,而不是用户交互处理。比之数据访问的低延迟问题,更关键的在于数据访问的高吞吐量。
1.4. 简单一致的模型
采用了"一次写入,多次读取"的模型。这一假设简化了数据一致性问题,并且使高吞吐量的数据访问成为可能。Map/Reduce应用或者网络爬虫应用都非常适合这个模型。目前还有计划在将来扩充这个模型,使之支持文件的附加写操作。
1.5. 可移植性
HDFS在设计的时候就考虑到平台的可移植性。这种特性方便了HDFS作为大规模数据应用平台的推广。 (可以这样理解:基于java,并且在HDFS是在本地FileSystem之上抽象出来的文件系统)
1.6. 移动计算比移动数据更高效
一个应用请求的计算,离它操作的数据越近就越高效,在数据达到海量级别的时候更是如此。因为这样就能降低网络阻塞的影响,提高系统数据的吞吐量。将计算移动到数据附近,比之将数据移动到应用所在显然更好。HDFS为应用提供了将它们自己移动到数据附近的接口。
一个简单的例子:程序X在计算机A上,数据在计算机A,B和C上。普通的做法是在A上运行程序X,读取A,B,C上的数据,然后进行计算(或者是边读取边计算)。hadoop的做法是:将程序X同时也发送到B和C上,A,B,C同时读取本地计算机上的数据进行计算。得出结果之后再进行汇总(当然这里只是通俗的举了个例子,实际上hadoop处理数据更为复杂)。这样就避免了在网络上传输大量数据导致的等待和B,C计算能力的浪费。
2. 概念:
nameNode 和 dataNode
HDFS采用了master/slave架构。HDFS由一个nameNode和若干个dataNode组成。
2.1 nameNode
nameNode类似于一个仓库管理员,负责记录数据存储在哪些仓库(dataNode)的哪些地方,同时也负责和客户端(Client)对文件的访问。nameNode作为一个中心服务器。因此当nameNode出现故障时是比较致命的。为了防止出现恶劣的后果,通常集群环境下还有一个Secondary NameNode 作为备份。
2.2 dataNode
dataNode负责文件的存储(可以理解为仓库)。
一个文件被分为多个文件块存储在一组dataNode里边。Namenode执行文件系统的名字空间操作,比如打开、关闭、重命名文件或目录。它也负责确定数据块到具体Datanode节点的映射。Datanode负责处理文件系统客户端的读写请求。在Namenode的统一调度下进行数据块的创建、删除和复制。
3. 文件流
3.1 读文件
客户端(client)用FileSystem的open()函数打开文件,DistributedFileSystem用RPC调用元数据节点,得到文件的数据块信息。对于每一个数据块,元数据节点返回保存数据块的数据节点的地址。DistributedFileSystem返回FSDataInputStream给客户端,用来读取数据。客户端调用stream的read()函数开始读取数据。DFSInputStream连接保存此文件第一个数据块的最近的数据节点。Data从数据节点读到客户端(client),当此数据块读取完毕时,DFSInputStream关闭和此数据节点的连接,然后连接此文件下一个数据块的最近的数据节点。当客户端读取完毕数据的时候,调用FSDataInputStream的close函数。
整个过程就是如图所示
3.2 写文件
客户端调用create()来创建文件,DistributedFileSystem用RPC调用元数据节点,在文件系统的命名空间中创建一个新的文件。元数据节点首先确定文件原来不存在,并且客户端有创建文件的权限,然后创建新文件。DistributedFileSystem返回DFSOutputStream,客户端用于写数据。客户端开始写入数据,DFSOutputStream将数据分成块,写入data queue。Data queue由Data Streamer读取,并通知元数据节点分配数据节点,用来存储数据块(每块默认复制3块)。分配的数据节点放在一个pipeline里。Data Streamer将数据块写入pipeline中的第一个数据节点。第一个数据节点将数据块发送给第二个数据节点。第二个数据节点将数据发送给第三个数据节点。DFSOutputStream为发出去的数据块保存了ack queue,等待pipeline中的数据节点告知数据已经写入成功。如果数据节点在写入的过程中失败:关闭pipeline,将ack queue中的数据块放入data queue的开始。
整个过程如图所示:
4. 使用命令行操作HDFS
1.添加目录 hadoop fs -mkdir /abc
就在HDFS下创建了一个abc的目录
2.列出HDFS根目录下的文件 hadoop fs -ls /
列出根目录下的所有文件 hadoop fs -ls
3.复制文件 hadoop fs -put /tianlong/test /abc
4.查看文件 hadoop fs -cat /abc/test
5.从HDFS上取文件 hadoop fs -get /abc/test ~/test.txt 把HDFS里的test文件 取回 当前用户目录的test.txt
5. 编程操作HDFS
下边简单介绍几个常用的API,具体的例子网上有很多,就不重复贴了。
FileSystem Hadoop文件系统通过Hadoop Path 对象来代表文件,是一个通用的文件系统API。
Hadoop中关于文件操作类基本上全部是在"org.apache.hadoop.fs"包中,这些API能够支持的操作包含:打开文件,读写文件,删除文件等。
Hadoop类库中最终面向用户提供的接口类是FileSystem,该类是个抽象类,只能通过来类的get方法得到具体类。get方法存在几个重载版本,常用的是这个:
static FileSystem get(Configuration conf) throws IOException;
static FileSystem get(URI uri, Configuration conf) throws IOException;
或者从Path对象中获得FileSystem实例
Path dst = new Path("hdfs://192.168.0.111:9000/home");
// 得到dst的FileSystem.
FileSystem hdfs = dst.getFileSystem(conf);
该类封装了几乎所有的文件操作,例如mkdir,delete等。综上基本上可以得出操作文件的程序库框架:
operator()
{
得到Configuration对象
得到FileSystem对象
进行文件操作
}