zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    Java 下载网络资源
    Java11 ThreadLocal的remove()方法源码分析
    软件测试的术语SRS,HLD,LLD,BD,FD,DD意义
    2020年12月2日
    20201129
    2020年11月28日
    程序员的三门课
    中间件到底是个什么鬼东西?
    接口测试框架的形成过程
    一个字符到底等于多少字节
  • 原文地址:https://www.cnblogs.com/erygreat/p/7352449.html
Copyright © 2011-2022 走看看