从零开始的Hadoop学习(五)| HDFS概述、shell操作、API操作

1. HDFS 概述

1.1 HDFS 产出背景及定义

1)HDFS 产生背景

随着数据量越来越大,在一个操作系统存不下所有的数据,那么就分配到更多的操作系统管理的磁盘中,但是不方便管理和维护,迫切 需要一种系统来管理多台机器上的文件 ,这就是分布式文件管理系统。 HDFS只是分布式文件管理系统中的一种。

2)HDFS定义

HDFS(Hadoop Distributed File System),它是一个文件系统 ,用于存储文件,通过目录树来定位文件: 其次,它是分布式的,由很多服务器联合起来实现其功能,集群中的服务器有各自的角色。

HDFS 的使用场景:适合一次写入,多次读出的场景。 一个文件经过创建写入和关闭之后就不需要改变。

1.2 HDFS 优缺点

HDFS优点

1)高容错性

  • 数据自动保存多个副本。它通过增加副本的形式,提高容错性。
  • 某一个副本丢失以后,它可以自动恢复。

2)适合处理大数据

  • 数据规模:能够处理数据规模达到GB、TB、甚至BP级别的数据;
  • 文件规模:能够处理百万规模以上的文件数量,数量相当之大。

3)可构建在廉价机器上,通过多副本机制,提高可靠性。

HDFS缺点

1)不适合低延时数据访问,比如毫秒级的存储数据,是做不到的。

2)无法高效的对大量小文件进行存储

  • 存储大量小文件的话,它会占用NameNode大量的内存来存储文件目录和块信息。这样是不可取的,因为NameNode的内存总是有限的;
  • 小文件存储的寻址时间会超过读取时间,它违反了 HDFS 的设计目标。

3)不支持并发写入,文件随机修改。

  • 一个文件只能有一个写,不允许多个线程同时写。
  • 仅支持append(追加),不支持文件的随机修改。

1.3 HDFS 组成架构

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

  • (1)管理HDFS的名称空间;
  • (2)配置副本策略;
  • (3)管理数据块(Block)隐射信息;
  • (4)处理客户端读写请求。

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

  • (1)存储实际的数据块;
  • (2)执行数据块的读/写操作。

3)Client:就是客户端。

  • (1)文件切分。文件上传HDFS的时候,Clinet将文件切分成一个一个的Block,然后进行上传;
  • (2)与NameNode交互,获取文件的位置信息;
  • (3)与DataNode交互,读取或者写入数据;
  • (4)Client提供一些命令来管理HDFS,不如NameNode格式化;
  • (5)Client可以通过一些命令来访问HDFS,比如对HDFS增删改操作;

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

  • (1)辅助NameNode,分组其工作量,比如定期合并Fsimage和Edits,并推送给NameNode;
  • (2)在紧急情况下,可辅助恢复NameNode。

1.4 HDFS 文件块大小(面试重点)

HDFS中的文件在物理上是分块存储(Block),块的大小可以通过配置参数(dis.blocksize)来规定, 默认大小在Hadoop2.x/3.x版本中是128M,1.x版本中是64M

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

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

总结:HDFS块的大小设置主要取决于磁盘传输速度。

2. HDFS的shell操作(开发重点)

2.1 基本语法

hadoop fs 具体命令 OR hdfs dfs具体命令。

2.2 命令大全

shell 复制代码
[atguigu@hadoop102 hadoop-3.1.3]$ bin/hadoop fs

[-appendToFile <localsrc> ... <dst>]
        [-cat [-ignoreCrc] <src> ...]
        [-chgrp [-R] GROUP PATH...]
        [-chmod [-R] <MODE[,MODE]... | OCTALMODE> PATH...]
        [-chown [-R] [OWNER][:[GROUP]] PATH...]
        [-copyFromLocal [-f] [-p] <localsrc> ... <dst>]
        [-copyToLocal [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
        [-count [-q] <path> ...]
        [-cp [-f] [-p] <src> ... <dst>]
        [-df [-h] [<path> ...]]
        [-du [-s] [-h] <path> ...]
        [-get [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
        [-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] <localsrc> ... <dst>]
        [-rm [-f] [-r|-R] [-skipTrash] <src> ...]
        [-rmdir [--ignore-fail-on-non-empty] <dir> ...]
<acl_spec> <path>]]
        [-setrep [-R] [-w] <rep> <path> ...]
        [-stat [format] <path> ...]
        [-tail [-f] <file>]
        [-test -[defsz] <path>]
        [-text [-ignoreCrc] <src> ...]

2.3 常用命令实操

2.3.1 准备工作

1)启动 Hadoop 集群(方便后续的测试)

shell 复制代码
[atguigu@hadoop102 hadoop-3.1.3]$ sbin/start-dfs.sh
[atguigu@hadoop103 hadoop-3.1.3]$ sbin/start-yarn.sh

2)-help:输出这个命令参数

shell 复制代码
[atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -help rm

3)创建/sanguo 文件夹

shell 复制代码
[atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -mkdir /sanguo

2.3.2 上传

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

shell 复制代码
[atguigu@hadoop102 hadoop-3.1.3]$ vim shuguo.txt
输入:
shuguo

[atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs  -moveFromLocal  ./shuguo.txt  /sanguo

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

shell 复制代码
[atguigu@hadoop102 hadoop-3.1.3]$ vim weiguo.txt
输入:
weiguo

[atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -copyFromLocal weiguo.txt /sanguo

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

shell 复制代码
[atguigu@hadoop102 hadoop-3.1.3]$ vim wuguo.txt
输入:
wuguo

[atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -put ./wuguo.txt /sanguo

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

shell 复制代码
[atguigu@hadoop102 hadoop-3.1.3]$ vim liubei.txt
输入:
liubei

[atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -appendToFile liubei.txt /sanguo/shuguo.txt

2.3.3 下载

1)-copyToLocal:从HDFS 拷贝到本地

shell 复制代码
[atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -copyToLocal /sanguo/shuguo.txt ./

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

shell 复制代码
[atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -get /sanguo/shuguo.txt ./shuguo2.txt

2.3.4 HDFS 直接操作

1)-ls:现实目录信息

复制代码
[atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -ls /sanguo

2)-cat:显示文件内容

复制代码
[atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -cat /sanguo/shuguo.txt

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

shell 复制代码

4)-mkdir:创建路径

shell 复制代码
[atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -mkdir /jinguo

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

shell 复制代码
[atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -cp /sanguo/shuguo.txt /jinguo

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

复制代码
[atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -mv /sanguo/wuguo.txt /jinguo
[atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -mv /sanguo/weiguo.txt /jinguo

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

shell 复制代码
[atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -tail /jinguo/shuguo.txt

8)-rm:删除文件或文件夹

shell 复制代码
[atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -rm /sanguo/shuguo.txt

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

shell 复制代码
[atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -rm -r /sanguo

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

shell 复制代码
[atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -du -s -h /jinguo
27  81  /jinguo

[atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -du  -h /jinguo
14  42  /jinguo/shuguo.txt
7   21   /jinguo/weiguo.txt
6   18   /jinguo/wuguo.tx

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

shell 复制代码
[atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -setrep 10 /jinguo/shuguo.txt

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

3. HDFS 的 API操作

3.1 客户端环境准备

1)找到资源包路径下的 Windows 依赖文件夹,拷贝 hadoop-3.1.0 到非中文路径(比如d:\)。

2)配置 HADOOP_HOME 环境变量

3)配置 Path 环境变量。

如果环境变量不起作用,可以重启电脑试试。

验证 Hadoop 环境变量是否正常。双击 winutils.exe,如果报如下错误。说明缺少微软运行库(正版系统往往有这个问题)。在资料包里面有对应的微软运行库安装包双击安装即可。

4)在 IDEA 中创建一个 Maven 工程 HdfsClientDemo,并凹入相应的依赖坐标+日志添加

xml 复制代码
<dependencies>
    <dependency>
        <groupId>org.apache.hadoop</groupId>
        <artifactId>hadoop-client</artifactId>
        <version>3.1.3</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.30</version>
    </dependency>
</dependencies>

在项目的 src/main/resources 目录下,新建一个文件,命名为 "log4j.properties",在文件中填入

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

5)创建包名:com.atguigu.hdfs

6)创建 HdfsClient 类

java 复制代码
package com.atguigu.hdfs;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.junit.Test;

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

/**
 * @author WangTingWei
 * @Date 2023/8/31 10:01
 * @description 客户端代码常用套路
 * 1、获取一个客户端对象
 * 2、执行相关的操作命令
 * 3、关闭资源
 * HDFS zookeeper
 */
public class HdfsClient {
    @Test
    public void testMkdirs() throws URISyntaxException, IOException, InterruptedException {
        // 1.获取文件系统
        Configuration configuration = new Configuration();
        // 用户
        String user = "atguigu";
        FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:8020"), configuration,user);
        // 2.创建目录
        fs.mkdirs(new Path("/xiyou/huaguoshan"));
        // 3.关闭资源
        fs.close();
    }
} 

7)执行程序

客户端去操作 HDFS 时,是有一个用户身份的。默认情况下,HDFS 客户端 API 会从采用 Windows 默认用户访问 HDFS,会报权限异常错误。所以在访问 HDFS时,一定要配置用户。

java 复制代码
package com.atguigu.hdfs;

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

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

/**
 * @author WangTingWei
 * @Date 2023/8/31 10:01
 * @description 客户端代码常用套路
 * 1、获取一个客户端对象
 * 2、执行相关的操作命令
 * 3、关闭资源
 * HDFS zookeeper
 */
public class HdfsClient {
    private FileSystem fs;

    @Before
    public void init() throws URISyntaxException, IOException, InterruptedException {
        // 连接的集群nn地址
        URI uri = new URI("hdfs://hadoop102:8020");
        Configuration configuration = new Configuration();
        // 用户
        String user = "atguigu";
         fs = FileSystem.get(uri,configuration,user);
    }

    @After
    public void close() throws IOException {
        fs.close();
    }

    @Test
    public void testMkdirs() throws URISyntaxException, IOException, InterruptedException {
        fs.mkdirs(new Path("/xiyou/huaguoshan1"));
    }
}

3.2 HDFS 的API 案例实操

3.2.1 HDFS 文件上传(测试参数优先级)

1)编写源代码

java 复制代码
    /**
     * 上传
     * 参数优先级
     * 代码里面的配置 > 在项目资源目录下的配置文件 > hdfs-site.xml > hdfs-default.xml 
     * @throws IOException
     */
    @Test
    public void testPut() throws IOException {
        //参数一:表示删除原数据;参数二:是否允许覆盖;参数三:原数据路径;参数四:目的地路径
        fs.copyFromLocalFile(true,true,new Path("D:\\sunwukong.txt"),new Path("hdfs://hadoop102/xiyou/huaguoshan"));
    }

2)将 hdfs-site.xml 拷贝到项目的 resource 资源目录下

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>

<configuration>
	<property>
		<name>dfs.replication</name>
         <value>1</value>
	</property>
</configuration>

3)参数优先级(从高到低)

  • (1)客户端代码中设置的值
  • (2)ClassPath下的用户自定义配置文件
  • (3)然后是服务器的自定义配置(xxx-site.xml)
  • (4)服务器的默认配置(xxx-default.xml)

3.2.2 HDFS 文件下载

java 复制代码
   /**
     * 下载
     */
    @Test
    public void testGet() throws IOException {
        //delSrc 是否将原文件删除;要下载的文件路径;文件下载到的路径;useRawLocalFileSystem 是否开启文件校验
        fs.copyToLocalFile(true,new Path("hdfs://hadoop102/xiyou/huaguoshan"),new Path("D:\\"),true);
    }
}

3.2.3 HDFS 文件更名和移动

java 复制代码
    /**
     * 文件更名和移动
     */
    @Test
    public void testRename() throws IOException {
        // 原文件路径;目标文件路径
        // 对文件名称的修改
        fs.rename(new Path("/output/_SUCCESS"),new Path("/output/SUCCESS"));
        // 文件的移动和更名
        fs.rename(new Path("/output/SUCCESS"),new Path("/SU"));
    }

3.2.4 HDFS 删除文件和目录

java 复制代码
    /**
     * 文件删除
     */
    @Test
    public void testRm() throws IOException {
        // 要删除的路径;是否递归删除
        fs.delete(new Path("/jinguo"), true);
    }

3.2.5 HDFS 文件详情查看

查看文件名称、权限、长度、块信息

java 复制代码
    /**
     * 获取文件信息详情
     */
    @Test
    public void fileDetail() 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.getModificationTime());
            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));
        }
    }

3.2.6 HDFS 文件和文件夹判断

java 复制代码
    @Test
    public void testListStatus() throws IOException, InterruptedException, URISyntaxException{
        // 判断是文件还是文件夹
        FileStatus[] listStatus = fs.listStatus(new Path("/"));
        for (FileStatus fileStatus : listStatus) {
            // 如果是文件
            if (fileStatus.isFile()) {
                System.out.println("f:"+fileStatus.getPath().getName());
            }else {
                System.out.println("d:"+fileStatus.getPath().getName());
            }
        }
    }
相关推荐
Q26433650231 小时前
【有源码】基于Python与Spark的火锅店数据可视化分析系统-基于机器学习的火锅店综合竞争力评估与可视化分析-基于用户画像聚类的火锅店市场细分与可视化研究
大数据·hadoop·python·机器学习·数据分析·spark·毕业设计
顧棟14 小时前
【Yarn实战】Yarn 2.9.1滚动升级到3.4.1调研与实践验证
hadoop·yarn
D明明就是我16 小时前
Hive 拉链表
数据仓库·hive·hadoop
嘉禾望岗50320 小时前
hive join优化和数据倾斜处理
数据仓库·hive·hadoop
yumgpkpm20 小时前
华为鲲鹏 Aarch64 环境下多 Oracle 数据库汇聚操作指南 CMP(类 Cloudera CDP 7.3)
大数据·hive·hadoop·elasticsearch·zookeeper·big data·cloudera
忧郁火龙果1 天前
六、Hive的基本使用
数据仓库·hive·hadoop
忧郁火龙果1 天前
五、安装配置hive
数据仓库·hive·hadoop
chad__chang1 天前
dolphinscheduler安装过程
hive·hadoop
ajax_beijing2 天前
hadoop的三副本数据冗余策略
大数据·hadoop·分布式
yumgpkpm3 天前
CMP (类ClouderaCDP7.3(404次编译) )华为鲲鹏Aarch64(ARM)信创环境多个mysql数据库汇聚的操作指南
大数据·hive·hadoop·zookeeper·big data·cloudera