HDFS(有时也成为DFS)是Hadoop的分布式文件系统。他可以将一个文件分布在多个主机上
例如:现在有一个200GB的文件,我们有5台电脑,每台存储为100GB,所以我们在一台电脑上是无法存放该文件的。这时我们就需要将其分区(就是切割成好几块)然后将它分别存储在各个主机上(每个电脑存储40GB的)。这就是HDFS的原理。
1. HDFS的特性
HDFS的优势:
超大文件存储
HDFS能够存储超大文件,几百MB,几百GB,几百TB,甚至几百PB
流式数据访问
流式数据,像流水一样,不是一次过来而是一点一点“流”过来。而处理流式数据也是一点一点处理。如果是全部收到数据以后再处理,那么延迟会很大,而且在很多场合会消耗大量内存。
商用硬件
就是普通的硬件,不需要昂贵可靠性高的硬件,只需要普通的PC机的硬件就可以。
HDFS的弊端:
延迟高
HDFS是为了高数据吞吐量应用优化的,相应的牺牲了时间,因此延迟较高。如果对延迟有要求可以用HBase
对小文件支持不好
文件的存储信息大约为150字节,如果大量小文件,例如一亿个,就需要namenode有30GB的内存,显然是不可以的。
文件只能添加/删除/追加,不能修改
HDFS文件只能添加/删除/追加,不能修改和多用户同时追加
2.HDFS数据块
HDFS的数据块很大,默认为64MB,很多情况下为128MB,这是为了最小化寻址开销。假设寻址时间为10ms,传输速率为100m/s,那么对于大数据块,寻址时间则大约为1%。
3. namenode和datanode
HDFS是以管理者-工作者的模式运行的。即有一个namenode和多个datanode,namenode管理文件系统的命名空间,以及文件信息。namenode也管理者各个文件中各个块所在的数据节点信息。
4.联邦HDFS
略
5.HDFS高可用
略
6.HDFS在Hadoop的配置
Hadoop中对HDFS有两个关键的配置
第一个是fs.default.name
设置默认的文件系统,设置为:hdfs://localhost:9000/
这样我们后面用到的绝对路径都是相对于这个路径。配置在core-site.xml
文件中
第二个是dfs.replication
设置副本数,HDFS通过设置多个副本冗余的方式来实现容错,默认设置为3,通过设置这个我们可以改变副本数目,例如在伪分布式下需要设置为1.
我们所常使用的文件操作,例如:读取文件,新建目录,移动文件,删除数据,列出目录等,HDFS都可以做到,我们使用hadoop fs -help
命令可以查询详细的帮助文档
[grid@tiny01 ~]$ hadoop fs -help
Usage: hadoop fs [generic options]
[-appendToFile ... ]
[-cat [-ignoreCrc] ...]
[-checksum ...]
[-chgrp [-R] GROUP PATH...]
[-chmod [-R] ... | OCTALMODE> PATH...]
[-chown [-R] [OWNER][:[GROUP]] PATH...]
[-copyFromLocal [-f] [-p] [-l] ... ]
[-copyToLocal [-p] [-ignoreCrc] [-crc] ... ]
[-count [-q] [-h] ...]
[-cp [-f] [-p | -p[topax]] ... ]
[-createSnapshot []]
[-deleteSnapshot ]
[-df [-h] [ ...]]
[-du [-s] [-h] ...]
[-expunge]
[-find ... ...]
[-get [-p] [-ignoreCrc] [-crc] ... ]
[-getfacl [-R] ]
[-getfattr [-R] {-n name | -d} [-e en] ]
[-getmerge [-nl] ]
[-help [cmd ...]]
[-ls [-d] [-h] [-R] [ ...]]
[-mkdir [-p] ...]
[-moveFromLocal ... ]
[-moveToLocal ]
[-mv ... ]
[-put [-f] [-p] [-l] ... ]
[-renameSnapshot ]
[-rm [-f] [-r|-R] [-skipTrash] ...]
[-rmdir [--ignore-fail-on-non-empty] ...]
[-setfacl [-R] [{-b|-k} {-m|-x } ]|[--set ]]
[-setfattr {-n name [-v value] | -x name} ]
[-setrep [-R] [-w] ...]
[-stat [format] ...]
[-tail [-f] ]
[-test -[defsz] ]
[-text [-ignoreCrc] ...]
[-touchz ...]
[-truncate [-w] ...]
[-usage [cmd ...]]
Generic options supported are
-conf specify an application configuration file
-D use value for given property
-fs specify a namenode
-jt specify a ResourceManager
-files specify comma separated files to be copied to the map reduce cluster
-libjars specify comma separated jar files to include in the classpath.
-archives specify comma separated archives to be unarchived on the compute machines.
The general command line syntax is
bin/hadoop command [genericOptions] [commandOptions]
例如,我们将一个本地文件复制到HDFS上,可以使用
[grid@tiny01 ~]$ hadoop fs -copyFromLocal easy.txt /easy.txt
[grid@tiny01 ~]$ hadoop fs -ls /
Found 2 items
-rw-r--r-- 1 grid supergroup 438736103 2017-07-10 02:30 /data.txt
-rw-r--r-- 1 grid supergroup 4783306 2017-07-21 23:39 /easy.txt
创建目录
[grid@tiny01 ~]$ hadoop fs -mkdir /tmp
[grid@tiny01 ~]$ hadoop fs -ls /
Found 3 items
-rw-r--r-- 1 grid supergroup 438736103 2017-07-10 02:30 /data.txt
-rw-r--r-- 1 grid supergroup 4783306 2017-07-21 23:39 /easy.txt
drwxr-xr-x - grid supergroup 0 2017-07-21 23:40 /tmp
等等
Hadoop可以使用多种文件系统,HDFS只是其中的一个实现。其中org.apache.hadoop.fs.FileSystem
是Hadoop文件系统的抽象类,其中有多种实现
文件系统 | URL方案 | Java实现(org.apache.hadoop包中) | 描述 |
---|---|---|---|
local | file | fs.LocalFileSystem | 本地文件系统 |
HDFS | hdfs | hdfs/DistributedFileSystem | Hadoop的分布式文件向系统 |
HFTP | Hftp | hdfs.hftpFileSystem | 一个HTTP上提供对HDFS只读访问的文件系统(和FTP无关) |
HSFTP | hsftp | hdfs.HsftpFileSystem | 同上 |
WebHDFS | Webhdfs | Hdfs.web.WebHdfsFileSystem | 基于HTTP,对HDFS提供安全读写访问的文件系统,替换了HSFTP,HFTP |
HAR | har | fs.HarFileSystem | 一个构建在其他文件系统之上用于文件存档的文件系统 |
FTP | ftp | fs.ftp.FTPFileSystem | 由FTP服务器支持的文件系统 |
Hadoop对文件系统提供了许多接口,如果我们想使用这些文件系统可以使用如下方式:
hadoop fs -ls file:///
但是建议使用HDFS文件系统。
我们介绍一下Hadoop的FileSystem类的使用。
1. 从URL中读取数据
读取hdfs URL需要使用FsUrlStreamHandlerFactory实例中的调用java.net.URL对象的setUrlStreamHandlerFactory方法,每个Java虚拟机中只能使用一次这个方法,因此通常在静态方法中使用。
import java.io.InputStream;
import java.net.URL;
import org.apache.hadoop.fs.FsUrlStreamHandlerFactory;
import org.apache.hadoop.io.IOUtils;
public class UrlCat {
static{
URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory());
}
public static void main(String[] args) throws Exception{
if(args.length < 1) {
throw new RuntimeException("请输入文件路径 !");
}
InputStream in = null;
try {
in = new URL(args[0]).openStream();
} finally{
IOUtils.closeStream(in);
}
IOUtils.copyBytes(in, System.out, 4096,false);
}
}
在Hadoop中运行:
[grid@tiny01 input]$ hadoop UrlCat file:///home/grid/input/word.txt
如果没有出结果可能没有设置HADOOP_CLASSPATH,需要在hadoop-env.sh中设置一下。
2.从FileSystemAPI中读取数据
前面说过,我们需要使用FsUrlStreamHandlerFactory实例中的调用java.net.URL对象的setUrlStreamHandlerFactory方法,但是每个Java虚拟机中只能使用一次这个方法。因此有时我们根本不可能在应用中设置他。这种情况下我们可以使用Hadoop的FileSystem API中打开文件。
import java.io.InputStream;
import java.net.URI;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
public class FileSystemCat {
public static void main(String[] args) throws Exception{
String url = args[0];
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(URI.create(url), conf);
InputStream in = null;
try {
in = fs.open(new Path(url));
IOUtils.copyBytes(in, System.out, 4096,false);
} catch (Exception e) {
IOUtils.closeStream(in);
}
}
}
3.写入数据
FileSystem中包含了一些列创建新文件的方法,最简单的方法是在指定一个Path对象,然后返回一个用于写入数据的工作流:
import java.net.URI;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
public class FileSystemCreate {
public static void main(String[] args) throws Exception{
String url = args[0];
String content = args[1];
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(URI.create(url), conf);
FSDataOutputStream outputStream = fs.create(new Path(url));
try {
outputStream.writeBytes(content);
outputStream.flush();
} catch (Exception e) {
IOUtils.closeStream(outputStream);
}
}
}
运行:
[grid@tiny01 input]$ hadoop FileSystemCreate file:///home/grid/input/word2.txt aaaaaaaa
[grid@tiny01 input]$ hadoop FileSystemCat file:///home/grid/input/word2.txt
aaaaaaaa
4. FileSystem的其他方法
FileSystem还有许多实用的方法,例如:
等等。
[1] Hadoop:The Definitive Guide,Third Edition, by Tom White. Copyright 2013 Tom White,978-1-449-31152-0