目录
- 写在前面
- 一、 hdfs概述
- 1.1 hdfs简介
- 1.2 hdfs优缺点
- 1.2.1 优点
- 1.2.2 缺点
 
- 1.3 hdfs组成架构
- 1.4 hdfs文件块大小
 
- 二、hdfs的shell操作(开发重点)
- 2.1 基本语法
- 2.2 命令大全
- 2.3 常用命令实操
- 2.3.1 上传
- 2.3.2 下载
- 2.3.3 hdfs直接操作
 
 
- 三、hdfs的api操作
- 3.1 配置windows
- 3.2 hdfs的api案例实操
- 3.2.1 hdfs文件上传
- 3.2.2 hdfs文件下载
- 3.2.3 hdfs文件更名和移动
- 3.2.4 hdfs删除文件和目录
- 3.2.5 hdfs文件详情查看
- 3.2.6 hdfs文件和文件夹判断
 
 
- 写在最后
写在前面
如今,数据正以指数级增长,各行各业都在追求更多的数据存储、高效的数据处理和可靠的数据基础来驱动业务的发展。hadoop distributed file system(hdfs)作为hadoop生态系统的核心组件之一,成为构建可靠的大数据基础的不二选择之一。本文将深入剖析hdfs的架构与优势。
一、 hdfs概述
1.1 hdfs简介
hdfs(hadoop分布式文件系统)是apache hadoop框架的一部分,设计用于存储和处理大规模数据集的分布式文件系统。hdfs产生的背景主要是为了满足处理大规模数据的需求。
在过去,传统的文件系统难以处理大规模数据集,因为它们通常只能在单个服务器上存储和操作数据。随着大数据时代的到来,企业和组织面临着巨大的数据规模和复杂性。为了应对这个挑战,hdfs被开发出来作为一个高度可靠和高容量的分布式文件系统。
hdfs的设计目标是能够在廉价的硬件上运行,并且能够容纳上千台机器的集群。它通过将数据切分成多个块并将其分散存储在不同的计算节点上,实现了高吞吐量的数据访问和处理能力。此外,hdfs还提供了故障容错功能,能够自动处理存储节点的故障。
简而言之,hdfs是为了解决大规模数据处理问题而设计的,它提供了高可靠性、高扩展性和高吞吐量的分布式文件系统解决方案。
1.2 hdfs优缺点
1.2.1 优点
- 高容错、高可用、高扩展 
  - 数据冗余多副本、副本丢失后自动恢复
- namenode ha、安全模式
- 10k节点规模,通过横向扩展来增加存储容量和处理能力。
 
- 海量数据存储(高容量) 
  - 典型文件大小gb~tb,百万以上文件数量,pb甚至eb以上数据规模
 
- 构建成本低、安全可靠 
  - 构建在廉价的商用服务器上,降低了存储成本和维护成本。
- 通过多副本机制,提高可靠性
- 提供了容错和恢复机制
 
- 适合大规模离线批处理 
  - 流式数据访问
- 数据位置暴露给计算框架
 
1.2.2 缺点
- 不适合低延迟数据访问 
  - 对于实时数据访问和低延迟要求较高的场景,hdfs的性能可能不够理想
 
- 不适合大量小文件存储 
  - 元数据会占用namenode大量存储空间
- 磁盘寻道时间超过读取时间
 
- 不支持并发写入 
  - 一个文件同时只能有一个写,不允许多个线程同时写
 
- 不支持文件随机修改 
  - 仅支持数据追加
 
1.3 hdfs组成架构

-  namenode(nn): 
 namenode是hdfs的主节点(master),负责管理整个文件系统的命名空间和数据块的元数据信息。它维护文件系统的目录结构、文件的安全权限信息和数据块的位置信息等。namenode还处理客户端的文件系统操作请求,如文件的读写和块的创建、复制和删除等。
-  datanode(dn): 
 datanode是hdfs的工作节点(slave),负责实际存储文件数据和执行文件系统操作的任务。每个datanode负责管理一定数量的数据块,并定期向namenode报告数据块的存储信息。datanode还处理来自客户端和其他datanode的读取和写入请求,以及数据块的复制和恢复等。
-  客户端(client): 
 客户端是使用hdfs的应用程序。它们通过与namenode和datanode进行通信来读取和写入文件。客户端向namenode请求文件的元数据信息,根据元数据信息确定所需数据块的位置,并从datanode获取数据。客户端还负责处理文件系统的操作,如创建、删除、重命名和移动文件等。
1.4 hdfs文件块大小
hdfs文件块的大小选择是根据以下考虑因素:
-  吞吐量:较大的文件块大小在处理大文件时可以提供更高的吞吐量。这是因为较大的文件块减少了磁盘寻道和网络传输的开销,使得数据读取和写入能够更加高效。 
-  空间利用:较大的文件块可以减少存储元数据的开销。在hdfs中,每个文件块都有一条元数据记录,较小的文件块可能会导致元数据记录数量增加,增加了存储的开销。 
-  并行性:较大的文件块可以提高数据的并行处理能力。在hdfs中,数据块是独立存储和处理的,较大的文件块能够在不同的计算节点上并行处理,从而减少整个作业的执行时间。 
较大的文件块适合存储大型文件和批量处理任务,但对于小型文件和实时数据处理,较小的文件块可能更加适合。
q:为什么hdfs文件块的大小不能太大,也不能设置太小呢?
 a: 文件块设置太小,会增加寻址的时间;设置太大,会导致数据处理非常慢。
hdfs文件块的大小设置取决于磁盘的传输速率
二、hdfs的shell操作(开发重点)
2.1 基本语法
hadoop fs 具体命令 或者 hdfs dfs 具体命令
2.2 命令大全
[amo@hadoop102 hadoop-3.2.4]$ bin/hadoop fs
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] [-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] <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]]
	[-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]
2.3 常用命令实操
- 创建一个文件夹,用来操作命令
[amo@hadoop102 hadoop-3.2.4]$ hadoop fs -mkdir /amoxilin
- help:输出这个命令参数
[amo@hadoop102 hadoop-3.2.4]$ hadoop fs -help rm
2.3.1 上传
- -movefromlocal:从本地剪切粘贴到hdfs
# 创建一个测试文件 test.txt,并输入一些内容
[amo@hadoop102 hadoop-3.2.4]$ vim test.txt
# 使用 movefromlocal 命令将test.txt文件移动到 hdfs
[amo@hadoop102 hadoop-3.2.4]$ hadoop fs -movefromlocal ./test.txt /amoxilin
- -copyfromlocal:从本地文件系统中拷贝文件到hdfs路径去
[amo@hadoop102 hadoop-3.2.4]$ vim test1.txt
[amo@hadoop102 hadoop-3.2.4]$ hadoop fs -copyfromlocal test1.txt /amoxilin
- -put:等同于copyfromlocal,生产环境更习惯用put
[amo@hadoop102 hadoop-3.2.4]$ hadoop fs -put test1.txt /amoxilin
- -appendtofile:追加一个文件到已经存在的文件末尾
# 创建一个文件test2.txt 并输入内容: 123
[amo@hadoop102 hadoop-3.2.4]$ vim test2.txt
# 将文件 test2.txt 追加到test.txt文件末尾
[amo@hadoop102 hadoop-3.2.4]$ hadoop fs -appendtofile test2.txt /amoxilin/test.txt

2.3.2 下载
- -copytolocal: 从hdfs拷贝到本地
# 将 hdfs 中的test.txt文件copy下来
[amo@hadoop102 hadoop-3.2.4]$ hadoop fs -copytolocal /amoxilin/test.txt ./
[amo@hadoop102 hadoop-3.2.4]$ ls  # 查看文件是否拷贝成功  文件夹中有 test.txt,拷贝成功
bin   etc      lib      license.txt  notice.txt  sbin   test1.txt  test.txt  wcoutput
data  include  libexec  logs         readme.txt  share  test2.txt  wcinput
[amo@hadoop102 hadoop-3.2.4]$ 
- -get: 等同于copytolocal,生产环境更习惯用get
# 将 hdfs 中的test.txt文件copy下来,并起一个其他的名字比如123.txt
[amo@hadoop102 hadoop-3.2.4]$ hadoop fs -get /amoxilin/test.txt ./123.txt
[amo@hadoop102 hadoop-3.2.4]$ ls
123.txt  etc      libexec      notice.txt  share      test.txt
bin      include  license.txt  readme.txt  test1.txt  wcinput
data     lib      logs         sbin        test2.txt  wcoutput
[amo@hadoop102 hadoop-3.2.4]$ 
2.3.3 hdfs直接操作
- -ls: 显示目录信息
# 查看 hdfs 里amoxilin文件夹的目录结构
[amo@hadoop102 hadoop-3.2.4]$ hadoop fs -ls /amoxilin
found 2 items
-rw-r--r--   3 amo supergroup          9 2024-03-07 23:33 /amoxilin/test.txt
-rw-r--r--   3 amo supergroup         49 2024-03-07 23:29 /amoxilin/test1.txt
- -cat: 显示文件内容
# 查看某个文件的详细信息
[amo@hadoop102 hadoop-3.2.4]$ hadoop fs -cat /amoxilin/test.txt
test
123
- -chgrp、-chmod、-chown: linux文件系统中的用法一样,修改文件所属权限
# 修改文件的权限
[amo@hadoop102 hadoop-3.2.4]$ hadoop fs -chmod 666 /amoxilin/test.txt
[amo@hadoop102 hadoop-3.2.4]$ hadoop fs -ls /amoxilin
found 2 items
-rw-rw-rw-   3 amo supergroup          9 2024-03-07 23:33 /amoxilin/test.txt
-rw-r--r--   3 amo supergroup         49 2024-03-07 23:29 /amoxilin/test1.txt
# 修改文件的group
[amo@hadoop102 hadoop-3.2.4]$ hadoop fs -chown amo:amo/amoxilin/test.txt
[amo@hadoop102 hadoop-3.2.4]$ hadoop fs -ls /amoxilin
found 2 items
-rw-rw-rw-   3 amo amo                 9 2024-03-07 23:33 /amoxilin/test.txt
-rw-r--r--   3 amo supergroup         49 2024-03-07 23:29 /amoxilin/test1.txt
- -mkdir: 创建路径
# 创建文件夹
[amo@hadoop102 hadoop-3.2.4]$ hadoop fs -mkdir /csdn
- -cp: 从hdfs的一个路径拷贝到hdfs的另一个路径
# 复制文件
[amo@hadoop102 hadoop-3.2.4]$ hadoop fs -cp /amoxilin/test1.txt /csdn
- -mv: 在hdfs目录中移动文件
# 移动文件
[amo@hadoop102 hadoop-3.2.4]$ hadoop fs -mv /amoxilin/test.txt /csdn
- -tail: 显示一个文件的末尾1kb的数据
# 查看文件末尾内容
[amo@hadoop102 hadoop-3.2.4]$ hadoop fs -tail /amoxilin/test1.txt
欲买桂花同载酒,终不似,少年游!
[amo@hadoop102 hadoop-3.2.4]$ 
- -rm: 删除文件或文件夹
# 删除
[amo@hadoop102 hadoop-3.2.4]$ hadoop fs -rm /amoxilin/test1.txt
deleted /amoxilin/test1.txt
- -rm -r: 递归删除目录及目录里面内容
# 递归删除
[amo@hadoop102 hadoop-3.2.4]$ hadoop fs -rm -r /amoxilin
deleted /amoxilin
- -u: 统计文件夹的大小信息
# 统计文件夹的大小
[amo@hadoop102 hadoop-3.2.4]$ hadoop fs -du -s -h /csdn
58  174  /csdn                                  # 58 是文件大小 文件有三个副本就是58*3=174
# 统计文件夹内各文件的大小
[amo@hadoop102 hadoop-3.2.4]$ hadoop fs -du -h /csdn
9   27   /csdn/test.txt
49  147  /csdn/test1.txt
- -setrep: 设置hdfs中文件的副本数量
# 设置hdfs副本数量
[amo@hadoop102 hadoop-3.2.4]$ hadoop fs -setrep 5 /csdn/test1.txt
replication 5 set: /csdn/test1.txt

这里设置的副本数只是记录在namenode的元数据中,是否真的会有这么多副本,还得看datanode的数量。因为目前只有3台设备,最多也就3个副本,只有节点数的增加到5台时,副本数才能达到5。
三、hdfs的api操作
3.1 配置windows
- 解压hadoop安装包到windows系统 d:\hadoop-3.2.4
- 设置$hadoop_home环境变量指向d:\hadoop-3.2.4
- 配置path环境变量 %hadoop_home%\bin
- 下载
- 将 hadoop.dll 和 winutils.exe 放入$hadoop_home/bin 文件夹中
3.2 hdfs的api案例实操
- 在idea中创建一个maven工程,并导入相应的依赖坐标以及日志
<dependencies>
    <dependency>
        <groupid>org.apache.hadoop</groupid>
        <artifactid>hadoop-client</artifactid>
        <version>3.2.4</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>
- 创建hdfsclient类
public class hdfsclient {
    @test
    public void test() throws ioexception, urisyntaxexception, interruptedexception {
		// 1 获取一个客户端实例
		// 参数1:hdfs文件系统地址
		// 参数2:配置文件
		// 参数3:用户
        filesystem fs= filesystem.get(new uri("hdfs://hadoop102:8020"),  new configuration(), "amo");
        
        // 2 创建目录
        fs.mkdirs(new path("/amxl"));
        // 3 关闭资源
        fs.close();
    }
}
- 执行程序
  
3.2.1 hdfs文件上传
- 编写源代码
 // 文件上传
@test
public void testcopyfromlocal() throws urisyntaxexception, ioexception, interruptedexception {
    // 1 获取一个客户端实例
    // 参数1:hdfs文件系统路径
    // 参数2:配置信息
    // 参数3:用户名
    filesystem fs = filesystem.get(new uri("hdfs://hadoop102:8020"),  new configuration(), "amo");
    // 2 使用客户端对象操作hdfs
    // copyfromlocalfile(是否删除源数据,是否覆盖目标数据,源数据路径,目标数据路径)
    fs.copyfromlocalfile(false, true, new path("d:\\note.txt"),new path("/amxl"));
    // 3 关闭资源
    fs.close();
}


 文件默认的副本为3
- 将hdfs-site.xml拷贝到项目的resources资源目录下,重新上传文件
<?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>

在resources目录下自定义配置文件并设置文件副本数为1,发现此处配置文件参数的优先级是高于默认配置的文件的
- 代码中修改配置
@test
public void testcopyfromlocal() throws urisyntaxexception, ioexception, interruptedexception {
    configuration configuration = new configuration();
    // 设置文件副本数为 2
    configuration.set("dfs.replication","2");
    filesystem fs = filesystem.get(new uri("hdfs://hadoop102:8020"),  configuration, "amo");
    fs.copyfromlocalfile(false, true, new path("d:\\note.txt"),new path("/amxl"));
    fs.close();
}

 重新上传文件,发现文件的副本数为2
- 小结
 参数优先级排序:客户端代码中设置的值 > resources下的用户自定义配置文件 >然后是服务器的自定义配置 >服务器的默认配置
3.2.2 hdfs文件下载
// 文件下载
@test
public void testcopytolocal() throws urisyntaxexception, ioexception, interruptedexception {
    // 1 获取配置信息以及加载配置 并获取一个客户端实例
    filesystem fs = filesystem.get(new uri("hdfs://hadoop102:8020"),  new configuration(), "amo");
    // 2 使用客户端对象操作 hdfs 将 note.txt文件下载到本地 d 盘
    // copytolocalfile(是否删除源文件,下载的文件路径,文件下载的目标路径,是否开启文件校验)
    fs.copytolocalfile(false,new path("/amxl/note.txt"),new path("d:\\"),true);
    // 3 关闭资源
    fs.close();
}
3.2.3 hdfs文件更名和移动
 // 文件移动和重命名
@test
public void testrename() throws ioexception, urisyntaxexception, interruptedexception {
    // 1 获取配置信息以及加载配置 并获取一个客户端实例
    filesystem fs = filesystem.get(new uri("hdfs://hadoop102:8020"), new configuration(), "amo");
    // 2 文件重命名
    // rename(源文件名,目标文件名)
    fs.rename(new path("/amxl/note.txt"), new path("/amxl/note1.txt"));
    // 文件移动
    // rename(源文件路径,目标文件路径)
    fs.rename(new path("/csdn/test1.txt"), new path("/amxl/test.txt"));
    // 3 关闭资源
    fs.close();
}
移动前:
 
移动后:
 
3.2.4 hdfs删除文件和目录
// 删除文件和文件夹
@test
public void testdelete() throws ioexception, urisyntaxexception, interruptedexception {
    // 1 获取配置信息以及加载配置 并获取一个客户端实例
    filesystem fs = filesystem.get(new uri("hdfs://hadoop102:8020"), new configuration(), "amo");
    // 2 文件删除
    // delete(路径)
    // delete(路径,是否递归)
    fs.delete(new path("/amxl/note1.txt"), false);
    fs.delete(new path("/csdn"), true);
    // 3 关闭资源
    fs.close();
}
删除前:
 
 删除后:
 
3.2.5 hdfs文件详情查看
查看文件名称、权限、长度、块信息
// 查看文件详细信息
@test
public void testgetfilestatus() throws ioexception, urisyntaxexception, interruptedexception {
    // 1 获取配置信息以及加载配置 并获取一个客户端实例
    filesystem fs = filesystem.get(new uri("hdfs://hadoop102:8020"), new configuration(), "amo");
    // 2 文件详细信息
    // liststatus(路径)
    // liststatus(路径,是否递归)
    remoteiterator<locatedfilestatus> listedfiles = fs.listfiles(new path("/amxl"), true);
    while (listedfiles.hasnext()) {
        locatedfilestatus next = listedfiles.next();
        system.out.println(next.getpath());
        system.out.println(next.getpermission());
        system.out.println(next.getowner());
        system.out.println(next.getgroup());
        system.out.println(next.getlen());
        system.out.println(next.getmodificationtime());
        system.out.println(next.getreplication());
        system.out.println(next.getblocksize());
        
		// 获取块信息
        blocklocation[] blocklocations = next.getblocklocations();
        system.out.println(arrays.tostring(blocklocations));
    }
    // 3 关闭资源
    fs.close();
}
// -----------------------------------------------------------------------------------------
// 输出
hdfs://hadoop102:8020/amxl/test.txt
rw-r--r--
amo
supergroup
49
1709910523258
5
134217728
[0,49,hadoop104,hadoop103,hadoop102]
3.2.6 hdfs文件和文件夹判断
 // 判断文件夹和文件
@test
public void testlistfiles() throws ioexception, urisyntaxexception, interruptedexception {
    // 1 获取配置信息以及加载配置 并获取一个客户端实例
    filesystem fs = filesystem.get(new uri("hdfs://hadoop102:8020"), new configuration(), "guo");
    // 2 判断文件夹和文件
    // liststatus(路径)
    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());
        }
    }
//        filestatus[] filestatuses = fs.liststatus(new path("/"));
//
//        for (filestatus filestatus : filestatuses) {
//            // 判断是否是文件夹
//            if (filestatus.isfile()) {
//                system.out.println("文件:" + filestatus.getpath().getname());
//            }
//            if (filestatus.isdirectory()) {
//                system.out.println("文件夹:" + filestatus.getpath().getname());
//            }
//        }
    // 3 关闭资源
    fs.close();
}

写在最后
总的来说,hdfs架构的优势和基本操作使其成为构建可靠的大数据基础的理想选择。它的高可靠性、高扩展性和高效的数据访问方式,为处理大规模数据提供了强大的支持,并通过shell操作和api操作,方便用户管理和操作存储在hdfs中的数据。
 
             我要评论
我要评论 
                                             
                                             
                                            
发表评论