Hadoop-5-HDFS

本文详细介绍了Hadoop的分布式文件系统HDFS,包括其概述、优缺点、架构设计、块的概念、命令操作、Java客户端操作、机架感知、文件上传下载流程、NameNode和SecondaryNameNode的工作机制、编辑日志和镜像文件、安全模式、多目录配置、DataNode工作机制等关键知识点,旨在帮助读者深入理解HDFS的运作和管理。
摘要由CSDN通过智能技术生成

Hadoop-5-HDFS

1、概述

 Hadoop Distributed File System (HDFS™),是一种分布式文件管理系统,用于管理多个机器上的文件

 它主要用于存储文件,通过目录树结构来定位文件的位置。适合一次写入,多次读出的场景,不支持文件的修改,所以用它做数据的分析,而不是当作网盘

2、优缺点

【1】优点

  1. 高容错性。容错性体现在数据保存到多个副本上(DataNode),并且可以通过增加副本的数量(replication),来提高这种特性。并且当一个副本的数据丢失后,它还可以自动恢复
  2. 大数据量。一是处理数据的量级,可以达到TB、PB的级别。二是文件的数量,能够处理百万以上的规模
  3. 流式数据。一次写入,多次写出。只能追加,不能修改。保证数据的一致性
  4. 高可用性。可以将数据节点部署到多个廉价机器上

【2】缺点

  1. 不能实现低延迟的数据访问。无法做到毫秒级的海量数据存储
  2. 无法高效地存储多个小文件。处理大量的小文件的存储、目录结构以及块信息,会占用NameNode的大量内存资源。此外小文件存储时的寻址时间会超过其读取时间,这违反了HDFS设计的初衷
  3. 不能并发写入和随机修改。对于一个文件,在同一时间内只能有一个写入,不允许多个线程同时写入。仅支持文件的追加,不支持文件的修改

3、架构设计

 主要由NameNode,DataNode和SecondaryNameNode组成

 需要注意的是SecondaryNameNode不是NameNode的热备,所以当NameNode节点挂掉时,其并不能立即替换NameNode并提供服务。SecondaryNameNode是一个用于监控HDFS状态的后台辅助程序,它每隔一段时间就会获取NameNode(HDFS元数据)的快照

4、块

 HDFS中的文件在物理上是分块存储(block),块的大小可以通过etc/hadoop/hdfs-site.xml中的dfs.blocksize来设置。apache hadoop 2.9.2默认大小为134217728(128MB)

 HDFS的块的大小比物理磁盘的块的大小要大,这是为了减少寻址的开销。如果块设置得足够大,那么数据传输的时间要明显地久于块寻址的时间

 寻址时间为传输时间的1%时,是最佳状态。计算公式:文件传输时间 = 磁盘寻址时间 / 0.01块的大小 = 文件传输时间 * 磁盘传输速率

 根据公式:假如寻址时间是10s,传输速率是100MB/s,那么块的大小 = 10s / 0.01 * 100MB/s = 100MB

5、命令操作【常用命令】

 所有命令都是通过bin/hadoop fs 命令的方式执行的。注意命令前面都有一个横杠

【1】创建目录

-mkdir -p,选项p表示递归,和Linux命令一样,不带参数仅创建一级目录

【2】查看目录

-ls -R,选项R表示递归,它会一直到目录的最里面

【3】删除目录

-rmdir

【4】上传文件

-copyFromLocal /本地文件 /HDFS目录,复制本地文件到HDFS

-put /本地文件 /HDFS目录,和copyFromLocal命令一样

-moveFromLocal /本地文件 /HDFS目录,移动本地文件到HDFS

【5】下载文件

-copyToLocal /HDFS文件 /本地目录,复制HDFS文件到本地

-get /HDFS文件 /本地目录,和copyToLocal命令一样

-moveToLocal /HDFS文件 /本地目录,移动HDFS文件到本地。

Hadoop 2.9.2,提示:moveToLocal: Option ‘-moveToLocal’ is not implemented yet.

【6】追加文件

-appendToFile /本地文件 /HDFS文件,将本地文件的内容追加到HDFS文件的末端

【7】查看文件

-cat /HDFS文件或目录,查看文件,可以使用*通配符,和Linux命令一样

-tail -f /HDFS文件,查看文件末尾,后41行,可以追加f选项,和Linux命令一样

【8】删除文件

-rm -r /HDFS目录或文件,删除文件或目录,和Linux命令一样

6、Java客户端操作

【1】准备环境

  1. Java
  2. Maven
  3. 和服务端一致的Hadoop,并解压缩到无中文目录
  4. 下载winutils,并将hadoop-2.8.3/bin目录里的winutils.exe复制到解压缩后的hadoop的bin目录当中
  5. 配置环境变量:HADOOP_HOME到解压缩目录
  6. 打开IDE。一定要先配置好环境变量再打开IDE

【2】MAVEN依赖

<properties>
    <!-- 和服务端版本一致 -->
    <hadoop.version>2.9.2</hadoop.version>
</properties>

<dependency>
    <!-- hadoop-client间接依赖hadoop-common -->
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-client</artifactId>
    <version>${hadoop.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-hdfs</artifactId>
    <version>${hadoop.version}</version>
</dependency>

【3】获取文件系统

通过org.apache.hadoop.fs.FileSystem对象的静态方法来获取

  1. FileSystem get(Configuration conf) throws IOException,需要传递一个org.apache.hadoop.conf.Configuration对象,该配置对象的属性,可以从etc/hadoop/core-site.xml中获取

    Configuration conf = new Configuration();
    // NameNode服务器的IP,9000是默认端口
    conf.set("fs.defaultFS", "hdfs://???.???.???.???:9000");
    FileSystem fileSystem = null;
    try {
         
        fileSystem = FileSystem.get(conf);
        System.out.println(fileSystem);
    } catch (IOException e) {
         
        e.printStackTrace();
    } finally {
         
        if (null != fileSystem) {
         
            try {
         
                fileSystem.close();
            } catch (IOException e) {
         
                e.printStackTrace();
            }
        }
    }
    
  2. FileSystem get(final URI uri, final Configuration conf, String user) throws IOException, InterruptedException

    URI uri = null;
    try {
         
        // NameNode服务器的IP,9000是默认端口
        uri = new URI("hdfs://???.???.???.???:9000");
    } catch (URISyntaxException e) {
         
        e.printStackTrace();
        return;
    }
    
    Configuration conf = new Configuration();
    FileSystem fileSystem = null;
    try {
         
        // 操作文件系统的用户名
        fileSystem = FileSystem.get(uri, conf, "???");
        System.out.println(fileSystem);
    } catch (IOException | InterruptedException e) {
         
        e.printStackTrace();
    } finally {
         
        if (null != fileSystem) {
         
            try {
         
                fileSystem.close();
            } catch (IOException e) {
         
                e.printStackTrace();
            }
        }
    }
    
  3. 【推荐】FileSystem get(URI uri, Configuration conf) throws IOException

    URI uri = null;
    try {
         
        // NameNode服务器的IP,9000是默认端口
        uri = new URI("hdfs://???.???.???.???:9000");
    } catch (URISyntaxException e) {
         
        e.printStackTrace();
        return;
    }
    
    // 操作文件系统的用户名。这句话也可以配置到vm参数当中-DHADOOP_USER_NAME=???
    System.setProperty("HADOOP_USER_NAME", "???");
    
    Configuration conf = new Configuration();
    FileSystem fileSystem = null;
    try {
         
        fileSystem = FileSystem.get(uri, conf);
        System.out.println(fileSystem);
    } catch (IOException e) {
         
        e.printStackTrace();
    } finally {
         
        if (null != fileSystem) {
         
            try {
         
                fileSystem.close();
            } catch (IOException e) {
         
                e.printStackTrace();
            }
        }
    }
    

【4】参数配置的优先级

 通过org.apache.hadoop.conf.Configuration对象配置参数的优先级是最高的。接着是classpath路径下的配置文件,如core-site.xml等。最后才是默认配置的参数

【5】创建目录

try {
   
    boolean mkdirs = fileSystem.mkdirs(new Path("/?/?/?"));
    System.out.println(mkdirs ? "成功" : "失败");
} catch (IOException e) {
   
    e.printStackTrace();
}

【6】查看目录

try {
   
    RemoteIterator<LocatedFileStatus> remoteIterator = fileSystem.listFiles(new Path("/"), true); // 第二个参数表示是否递归

    System.out.println("Permission\tOwner\tGroup\t\tSize\tLast Modified\tPath\t\tReplication");
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM-dd HH:mm");

    while (remoteIterator.hasNext()) {
   
        LocatedFileStatus locatedFileStatus = remoteIterator.next();

        String permission = locatedFileStatus.getPermission().toString();
        StringBuilder line = new StringBuilder(permission).append("\t");

        String owner = locatedFileStatus.getOwner();
        line.append(owner).append("\t");

        String group = locatedFileStatus.getGroup();
        line.append(group).append("\t");

        long size = locatedFileStatus.getLen();
        line.append(size).append("\t");

        long lastModified = locatedFileStatus.getModificationTime();
        String time = simpleDateFormat.format(new Date(lastModified));
        line.append(time).append("\t\t");

        Path path = locatedFileStatus.getPath();
        String pathStr = path
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值