1.HDFS简介
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.
02.HDFS命令行接口
我们所常使用的文件操作,例如:读取文件,新建目录,移动文件,删除数据,列出目录等,HDFS都可以做到,我们使用hadoop fs -help
命令可以查询详细的帮助文档
[grid@tiny01 ~]$ hadoop fs -help
Usage: hadoop fs [generic options]
[-appendToFile <localsrc> ... <dst>]
[-cat [-ignoreCrc] <src> ...]
[-checksum <src> ...]
[-chgrp [-R] GROUP PATH...]
[-chmod [-R] <MODE[,MODE]... | OCTALMODE> PATH...]
[-chown [-R] [OWNER][:[GROUP]] PATH...]
[-copyFromLocal [-f] [-p] [-l] <localsrc> ... <dst>]
[-copyToLocal [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
[-count [-q] [-h] <path> ...]
[-cp [-f] [-p | -p[topax]] <src> ... <dst>]
[-createSnapshot <snapshotDir> [<snapshotName>]]
[-deleteSnapshot <snapshotDir> <snapshotName>]
[-df [-h] [<path> ...]]
[-du [-s] [-h] <path> ...]
[-expunge]
[-find <path> ... <expression> ...]
[-get [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
[-getfacl [-R] <path>]
[-getfattr [-R] {-n name | -d} [-e en] <path>]
[-getmerge [-nl] <src> <localdst>]
[-help [cmd ...]]
[-ls [-d] [-h] [-R] [<path> ...]]
[-mkdir [-p] <path> ...]
[-moveFromLocal <localsrc> ... <dst>]
[-moveToLocal <src> <localdst>]
[-mv <src> ... <dst>]
[-put [-f] [-p] [-l] <localsrc> ... <dst>]
[-renameSnapshot <snapshotDir> <oldName> <newName>]
[-rm [-f] [-r|-R] [-skipTrash] <src> ...]
[-rmdir [--ignore-fail-on-non-empty] <dir> ...]
[-setfacl [-R] [{-b|-k} {-m|-x <acl_spec>} <path>]|[--set <acl_spec> <path>]]
[-setfattr {-n name [-v value] | -x name} <path>]
[-setrep [-R] [-w] <rep> <path> ...]
[-stat [format] <path> ...]
[-tail [-f] <file>]
[-test -[defsz] <path>]
[-text [-ignoreCrc] <src> ...]
[-touchz <path> ...]
[-truncate [-w] <length> <path> ...]
[-usage [cmd ...]]
Generic options supported are
-conf <configuration file> specify an application configuration file
-D <property=value> use value for given property
-fs <local|namenode:port> specify a namenode
-jt <local|resourcemanager:port> specify a ResourceManager
-files <comma separated list of files> specify comma separated files to be copied to the map reduce cluster
-libjars <comma separated list of jars> specify comma separated jar files to include in the classpath.
-archives <comma separated list of 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
等等
03.Hadoop文件系统
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文件系统。
04.Hadoop文件管理类:FileSystem
我们介绍一下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还有许多实用的方法,例如:
- 文件追加内容:append()
- 创建目录:mkdirs()
- 查询文件状态:getFileStatus()
- 检查文件/目录是否存在:exist()
- 列出目录中的文件状态:listStatus()
- 删除文件/目录:delete(),第二个参数,是删除有内容的目录的。
等等。
05.参考资料
[1] Hadoop:The Definitive Guide,Third Edition, by Tom White. Copyright 2013 Tom White,978-1-449-31152-0