尚硅谷hadoop3.x-HDFS(1)

本文介绍了HDFS的组成部分,包括NameNode、DataNode、SecondaryNameNode和客户端的角色,以及HDFS文件块大小的设定原则。同时,详细列举了HDFS的Shell操作命令,包括上传、下载、删除、移动文件等,并提到了API操作的基本流程和配置依赖。
摘要由CSDN通过智能技术生成

一. HDFS概述

1. HDFS组成架构

在这里插入图片描述

  1. NameNode(nn):就是Master,它 是一个主管、管理者。

    NameNode是HDFS中的主节点,负责管理整个文件系统的命名空间和元数据。它记录了文件和数据块的映射关系,并维护了文件系统的目录结构。NameNode还负责处理客户端的读写请求,指导数据节点进行数据的读写操作。由于NameNode存储了整个文件系统的元数据,因此它需要足够的内存和计算资源来支持大规模数据集。

  2. DateNode(dn):就是Slave。NameNode 下达命令,DataNode执行实际的操作。

    DataNode是HDFS中的工作节点,负责存储实际的数据块。每个数据节点上都会存储一部分数据块,并定期向NameNode发送心跳信号,报告自己的存活状态和数据块的信息。DataNode主要执行数据的读写操作,根据NameNode的指导,将数据块复制到其他数据节点上以实现数据的冗余和容错性。

  3. Client:就是客户端。

    客户端是与HDFS交互的应用程序或用户界面。客户端通过与NameNode通信来获取文件的元数据信息,包括文件的大小、分块信息等。然后客户端可以直接与数据节点交互来读取或写入数据。客户端还可以通过HDFS提供的API来进行文件操作,例如创建、删除、移动和重命名文件等。

  4. Secondary NameNode:并非NameNode的热备。当NameNode挂掉的时候,它并不 能马上替换NameNode并提供服务。

    Secondary NameNode并不是NameNode的备份,它是一个辅助性的节点,用于帮助NameNode管理元数据。Secondary NameNode定期从NameNode获取元数据的快照,并将其保存在本地磁盘上。它还可以协助NameNode进行元数据的合并和清理工作,以提高系统的性能和稳定性。

2. HDFS文件块大小

在这里插入图片描述

寻址时间除以1%(即0.01)得到传输时间,然后传输时间乘100MB/s所得结果即为块大小。但是在计算机领域,1024才是整数,所以看求出的块大小接近128MB还是256MB,接近哪个,块大小就设置成哪个。

为什么块的大小不能设置太小,也不能设置太大?

  1. HDFS的块设置太小,会增加寻址时间,程序一直在找块的开始位置。
  2. 如果块设置的太大,从磁盘传输数据的时间会明显大于定位这个块开 始位置所需的时间。导致程序在处理这块数据时,会非常慢。

总结::HDFS块的大小设置主要取决于磁盘传输速率(即磁盘读写速度)。在企业开发中,常见的为128MB或256MB,一般大公司用256MB。中小公司用128MB。

二. HDFS的操作

HDFS的操作分为Shell操作和API操作,当然也包括在网页上直接操作。

HDFS的Shell操作

基本语法:

方式一:hadoop fs 具体命令
方式二:hdfs dfs 具体命令

方式一和方式二的效果是完全相同的,且命令的前面都有一个杠-

命令大全:

输入hadoop fs就能看见所以的命令:

[root@hadoop102 ~]# hadoop fs
Usage: hadoop fs [generic options]
	[-appendToFile [-n] <localsrc> ... <dst>]
	[-cat [-ignoreCrc] <src> ...]
	[-checksum [-v] <src> ...]
	[-chgrp [-R] GROUP PATH...]
	[-chmod [-R] <MODE[,MODE]... | OCTALMODE> PATH...]
	[-chown [-R] [OWNER][:[GROUP]] PATH...]
	[-concat <target path> <src path> <src path> ...]
	[-copyFromLocal [-f] [-p] [-l] [-d] [-t <thread count>] [-q <thread pool queue size>] <localsrc> ... <dst>]
	[-copyToLocal [-f] [-p] [-crc] [-ignoreCrc] [-t <thread count>] [-q <thread pool queue size>] <src> ... <localdst>]
	[-count [-q] [-h] [-v] [-t [<storage type>]] [-u] [-x] [-e] [-s] <path> ...]
	[-cp [-f] [-p | -p[topax]] [-d] [-t <thread count>] [-q <thread pool queue size>] <src> ... <dst>]
	[-createSnapshot <snapshotDir> [<snapshotName>]]
	[-deleteSnapshot <snapshotDir> <snapshotName>]
	[-df [-h] [<path> ...]]
	[-du [-s] [-h] [-v] [-x] <path> ...]
	[-expunge [-immediate] [-fs <path>]]
	[-find <path> ... <expression> ...]
	[-get [-f] [-p] [-crc] [-ignoreCrc] [-t <thread count>] [-q <thread pool queue size>] <src> ... <localdst>]
	[-getfacl [-R] <path>]
	[-getfattr [-R] {-n name | -d} [-e en] <path>]
	[-getmerge [-nl] [-skip-empty-file] <src> <localdst>]
	[-head <file>]
	[-help [cmd ...]]
	[-ls [-C] [-d] [-h] [-q] [-R] [-t] [-S] [-r] [-u] [-e] [<path> ...]]
	[-mkdir [-p] <path> ...]
	[-moveFromLocal [-f] [-p] [-l] [-d] <localsrc> ... <dst>]
	[-moveToLocal <src> <localdst>]
	[-mv <src> ... <dst>]
	[-put [-f] [-p] [-l] [-d] [-t <thread count>] [-q <thread pool queue size>] <localsrc> ... <dst>]
	[-renameSnapshot <snapshotDir> <oldName> <newName>]
	[-rm [-f] [-r|-R] [-skipTrash] [-safely] <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] [-s <sleep interval>] <file>]
	[-test -[defswrz] <path>]
	[-text [-ignoreCrc] <src> ...]
	[-touch [-a] [-m] [-t TIMESTAMP (yyyyMMdd:HHmmss) ] [-c] <path> ...]
	[-touchz <path> ...]
	[-truncate [-w] <length> <path> ...]
	[-usage [cmd ...]]

Generic options supported are:
-conf <configuration file>        specify an application configuration file
-D <property=value>               define a value for a given property
-fs <file:///|hdfs://namenode:port> specify default filesystem URL to use, overrides 'fs.defaultFS' property from configurations.
-jt <local|resourcemanager:port>  specify a ResourceManager
-files <file1,...>                specify a comma-separated list of files to be copied to the map reduce cluster
-libjars <jar1,...>               specify a comma-separated list of jar files to be included in the classpath
-archives <archive1,...>          specify a comma-separated list of archives to be unarchived on the compute machines

The general command line syntax is:
command [genericOptions] [commandOptions]

此外,还可以通过-help来获得某个命令的具体用法:

-help:输出这个命令参数

[root@hadoop102 ~]# hadoop fs -help setrep
-setrep [-R] [-w] <rep> <path> ... :
  Set the replication level of a file. If <path> is a directory then the command
  recursively changes the replication factor of all files under the directory tree
  rooted at <path>. The EC files will be ignored here.
                                                                                 
  -w  It requests that the command waits for the replication to complete. This   
      can potentially take a very long time.                                     
  -R  It is accepted for backwards compatibility. It has no effect.   

1. 上传

-moveFromLocal:从本地剪切粘贴到HDFS

hadoop fs  -moveFromLocal  ./shuguo.txt  /sanguo

-copyFromLocal:从本地文件系统中拷贝文件到HDFS路径去

hadoop fs -copyFromLocal weiguo.txt /sanguo

-put:等同于copyFromLocal,生产环境更习惯用put

hadoop fs -put ./wuguo.txt /sanguo

-appendToFile:追加一个文件到已经存在的文件末尾

hadoop fs -appendToFile liubei.txt /sanguo/shuguo.txt

2. 下载

-copyToLocal:从HDFS拷贝到本地

hadoop fs -copyToLocal /sanguo/shuguo.txt ./

-get:等同于copyToLocal,生产环境更习惯用get

hadoop fs -get /sanguo/shuguo.txt ./shuguo2.txt

3. HDFS直接操作

与Linux命令非常相像,若命令后面还要跟上参数的话,则必须空一格再加参数!!千万不能像Linux一样将两个参数合在一起写!!!

如:rm后可接两个参数-r-f,在Linux中我们可以写rm -rf,但是在Shell中我们不能这样写hadoop fs -rm -rf ,得写成hadoop fs -rm -r -f

[root@hadoop102 ~]# hadoop fs -rm -r -f /xiyou
Deleted /xiyou

当然,-f表示强制删除,不需要询问我们。而hdfs不会问我们,所以敲hadoop fs -rm -r就行了,只不过敲-f也不会报错啦。

-ls: 显示目录信息

hadoop fs -ls /sanguo

-cat:显示文件内容

hadoop fs -cat /sanguo/shuguo.txt

-chgrp、-chmod、-chown:Linux文件系统中的用法一样,修改文件所属权限

hadoop fs  -chgrp  root /sanguo/shuguo.txt
hadoop fs  -chmod  666  /sanguo/shuguo.txt
hadoop fs  -chown  root:root   /sanguo/shuguo.txt

-mkdir:创建路径

hadoop fs -mkdir /jinguo

-cp:从HDFS的一个路径拷贝到HDFS的另一个路径

hadoop fs -cp /sanguo/shuguo.txt /jinguo

-mv:在HDFS目录中移动文件

hadoop fs -mv /sanguo/weiguo.txt /jinguo
hadoop fs -mv /Lecture1.pdf /guoting.pdf

注:当目的地是目录时,就是单纯的移动文件。若目的地是文件,则相当于剪切过去再重命名。没错,给文件或目录重命名的实质就是剪切并重命名,只不过路径没有发生变化只更改名字罢了。

-tail:显示一个文件的末尾1kb的数据

hadoop fs -tail /jinguo/shuguo.txt

-rm:删除文件或文件夹

hadoop fs -rm /sanguo/shuguo.txt

-rm -r:递归删除目录及目录里面内容

hadoop fs -rm -r /sanguo

-du:统计文件夹的大小信息

hadoop fs -du /jinguo

当然,我们一般使用命令-du会加上-h,这样文件大小更容易读。此外,更常用的命令是hadoop fs -du -s -h,只显示总和,和Linux一样。只不过需要注意别把-s -h写成-sh就行。

-setrep:设置HDFS中文件的副本数量

hadoop fs -setrep 10 /jinguo/shuguo.txt

注意:这里设置的副本数只是记录在NameNode的元数据中,是否真的会有这么多副本,还得看DataNode的数量。因为目前只有3台设备,最多也就3个副本,只有节点数的增加到10台时,副本数才能达到10。

HDFS的API操作

1. 客户端环境准备

配置依赖:

首先需要下载与hadoop同版本Windows依赖文件,并拷贝到非中文路径。

然后配置系统HADOOP_HOME环境变量。

接着配置Path环境变量。(注意:如果环境变量不起作用,可以重启电脑试试。

最后验证Hadoop环境变量是否正常:双击winutils.exe,若出现一个一闪而过的窗口则说明正常。

配置Maven:

可以按照一位大神写的教程(传送门)一步步配。只需要注意正确输入自己的hadoop和jdk版本即可,除非版本一模一样,否则千万别直接无脑复制粘贴!

2. IDEA操作

新建工程HDFSClient:

点击new project,输入名字HDFSClient,将Build system选择为Maven,最后修改Advanced Settings中的Groupld即可(这个选项相当于设置包名,一般采用公司域名的倒置作为名字)。

修改IDEA中的Maven配置:

点开设置,搜索"maven",然后点击"Maven"(直接点,别将它展开),再将系统自带的Maven其修改为自己配置的,需要修改的地方有三处,按照自己的Maven进行相应的设置即可。

在这里插入图片描述

然后点击设置中目前所在的"Maven"下面的"Importing",找到"VM options for importer",输入下面这行话:

-Dmaven.wagon.http.ssl.insecure=true -Dmaven.wagon.http.ssl.allowall=true 

在这里插入图片描述

这样设置是:忽略SSL证书验证,防止连不到阿里云的服务器无法自动下载依赖,而出现找不到依赖的错误 。

导入相应的依赖坐标+日志添加:

创建完Maven工程后会自动生成一些代码,在其中的</properties></project>之间添加以下内容(注意自己的hadoop版本):

<dependencies>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>3.3.6</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>2.0.5</version>
        </dependency>
    </dependencies>

因为是首次添加,所以需要让idea联网下载一些文件:点击右边侧边栏的Maven,然后点击页面顶端的刷新图标,之后耐心等待即可。

新建文件log4j.properties:

在项目的src/main/resources目录下,新建一个文件,命名为“log4j.properties”,在文件中填入以下内容:

log4j.rootLogger=INFO, stdout  
log4j.appender.stdout=org.apache.log4j.ConsoleAppender  
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout  
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n  
log4j.appender.logfile=org.apache.log4j.FileAppender  
log4j.appender.logfile.File=target/spring.log  
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout  
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n

创建包com.用户名.hdfs并创建Java类HdfsClient:

之后就可以在这个类中调用API控制hdfs了。

package com.用户名.hdfs;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;

/**
 * 客户端代码常用套路:
 * 1. 获取一个客户端对象
 * 2. 执行相关的操作命令
 * 3. 关闭资源
 */

public class HdfsClient {

    private FileSystem fs;

    @Before
    public void init() throws IOException, InterruptedException, URISyntaxException {

        // 连接集群的nn地址
        URI uri = new URI("hdfs://hadoop102:8020");
        // 创建一个配置文件
        Configuration configuration = new Configuration();
        configuration.set("dfs.replication", "2"); // 修改副本数
        // 用户
        String user = "root";

        // 1. 获取到了客户端对象
        fs = FileSystem.get(uri, configuration, user);
    }

    @After
    public void close() throws IOException {

        // 3. 关闭资源
        fs.close();

    }

    @Test
    public void testMkdir() throws URISyntaxException, IOException, InterruptedException {
        
        // 2. 创建一个文件夹 
        fs.mkdirs(new Path("/xiyou/huaguoshang"));
        
    }

    /**
     * 参数优先级:
     * hdfs-default.xml -> hdfs-site.xml -> 在项目资源目录下的配置文件 -> 代码里面的配置
     *
     * @throws IOException
     */
    @Test
    public void testPut() throws IOException {
        fs.copyFromLocalFile(false, true, new Path("D:\\testapi\\sunwukong.txt"), new Path("/xiyou/huaguoshang/"));
    }

    @Test
    public void testRm() throws IOException {
        fs.delete(new Path("/xiyou/huaguoshang/sunwukong.txt"), false);
    }

    @Test
    public void testMv() throws IOException {

        // 移动
        fs.rename(new Path("/sunwukong.txt"), new Path("/xiyou/huaguoshang/sunwukong.txt"));

        // 重命名
        //fs.rename(new Path("/xiyou/huaguoshang/sunwukong.txt"), new Path("/xiyou/huaguoshang/wukong.txt"));
    }

    @Test
    public void testGet() throws IOException {
        fs.copyToLocalFile(false, new Path("/xiyou/huaguoshang"), new Path("D:\\testapi"), false);
    }

    @Test
    public void testListFiles() throws IOException {

        RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/"), true);
        while (listFiles.hasNext()) {
            LocatedFileStatus fileStatus =  listFiles.next();
            System.out.println("==========" + fileStatus.getPath() + "==========");
            System.out.println(fileStatus.getPermission());
            System.out.println(fileStatus.getOwner());
            System.out.println(fileStatus.getGroup());
            System.out.println(fileStatus.getLen());
            System.out.println(fileStatus.getAccessTime());
            System.out.println(fileStatus.getReplication());
            System.out.println(fileStatus.getBlockSize());
            System.out.println(fileStatus.getPath().getName());

            // 获取块信息
            BlockLocation[] blockLocations = fileStatus.getBlockLocations();
            System.out.println(Arrays.toString(blockLocations));
        }
    }

    @Test
    public void testFiles() throws IOException {

        FileStatus[] fileStatuses = fs.listStatus(new Path("/"));
        for (FileStatus fileStatus: fileStatuses) {
            if (fileStatus.isFile()) System.out.println("文件:" + fileStatus.getPath().getName());
            else System.out.println("文件目录:" + fileStatus.getPath().getName());
        }

    }

}

客户端代码常用套路:

  1. 获取一个客户端对象
  2. 执行相关的操作命令
  3. 关闭资源

参数优先级:

hdfs-default.xml -> hdfs-site.xml -> 在项目资源目录下的配置文件 -> 代码里面的配置

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值