hadoop2.x之HDFS

1.HDFS简介

HDFS(有时也成为DFS)是Hadoop的分布式文件系统。他可以将一个文件分布在多个主机上

例如:现在有一个200GB的文件,我们有5台电脑,每台存储为100GB,所以我们在一台电脑上是无法存放该文件的。这时我们就需要将其分区(就是切割成好几块)然后将它分别存储在各个主机上(每个电脑存储40GB的)。这就是HDFS的原理。

1. HDFS的特性

HDFS的优势:

  • 超大文件存储
    HDFS能够存储超大文件,几百MB,几百GB,几百TB,甚至几百PB

  • 流式数据访问
    流式数据,像流水一样,不是一次过来而是一点一点“流”过来。而处理流式数据也是一点一点处理。如果是全部收到数据以后再处理,那么延迟会很大,而且在很多场合会消耗大量内存。

  • 商用硬件
    就是普通的硬件,不需要昂贵可靠性高的硬件,只需要普通的PC机的硬件就可以。

HDFS的弊端:

  • 延迟高
    HDFS是为了高数据吞吐量应用优化的,相应的牺牲了时间,因此延迟较高。如果对延迟有要求可以用HBSE

  • 对小文件支持不好
    文件的存储信息大约为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

posted on 2017-08-13 09:26  erygreat  阅读(344)  评论(0编辑  收藏  举报

导航