Hadoop 学习(三)——HDFS概述、shell操作、API操作

220 阅读6分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第15天,点击查看活动详情


⭐️前面的话⭐️

✉️坚持和努力一定能换来诗与远方!
💭推荐书籍:📚《王道408》,📚《深入理解 Java 虚拟机-周志明》,📚《Java 核心技术卷》
💬算法刷题:✅力扣🌐牛客网
🎈Github
🎈码云Gitee


HDFS

5 HDFS 概述

5.1HDFS 产生背景、定义和使用场景

  • 产生背景

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

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

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

5.2HDFS 优缺点

  • 优点

    • 高容错性:数据自动保存多个副本。某一个副本丢失以后,可以自动恢复。
    • 适合处理大数据
      • 数据规模:能够处理数据规模达到GB、TB甚至PB级别的数据
      • 文件规模:能够处理百万规模以上的文件数量,数量相当之大。
    • 可构建在廉价机器上,通过多副本机制,提高可靠性。
  • 缺点

    • 不适合低延时数据访问(比如毫秒级的存储数据)
    • 无法高效地对大量小文件进行存储(寻址时间会超过读取时间)
    • 不支持并发写入(不允许多个文件同时写)、不支持文件随机修改(仅支持数据 append 追加)

5.3HDFS 组成架构

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

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

  • 不能设置太小,也不能设置太大?

    • 太小,会增加寻址时间
    • 太大,程序在处理这块数据时,会非常慢
    • HDFS块的大小设置主要取决于磁盘传输速率。

6 HDFS 的shell操作🎈(开发重点)

6.1基本语法

  • hadoop fs 具体命令
  • hdfs dfs 具体命令

6.2命令大全

 [atguigu@hadoop102 hadoop-3.1.3]$ bin/hadoop fs

6.3常用命令实操

准备工作

  • 启动Hadoop集群(方便后续的测试)
 [atguigu@hadoop102 hadoop-3.1.3]$ sbin/start-dfs.sh
 [atguigu@hadoop103 hadoop-3.1.3]$ sbin/start-yarn.sh
  • -help:输出这个命令参数
 [atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -help rm
  • 创建/sanguo文件夹
 [atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -mkdir /sanguo

上传

  • -moveFromLocal:从本地剪切粘贴到 HDFS
 [atguigu@hadoop102 hadoop-3.1.3]$ vim shuguo.txt
 输入:
 shuguo
 ​
 [atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs  -moveFromLocal  ./shuguo.txt  /sanguo
  • -copyFromLocal:从本地文件系统中拷贝文件到 HDFS 路径去
 [atguigu@hadoop102 hadoop-3.1.3]$ vim weiguo.txt
 输入:
 weiguo
 ​
 [atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -copyFromLocal weiguo.txt /sanguo
  • -put:等同于copyFromLocal,生产环境更习惯用put
 [atguigu@hadoop102 hadoop-3.1.3]$ vim wuguo.txt
 输入:
 wuguo
 ​
 [atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -put ./wuguo.txt /sanguo
  • -appendToFile:追加一个文件到已经存在的文件末尾
 [atguigu@hadoop102 hadoop-3.1.3]$ vim liubei.txt
 输入:
 liubei
 ​
 [atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -appendToFile liubei.txt /sanguo/shuguo.txt

下载

  • -copyToLocal:从HDFS拷贝到本地
 [atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -copyToLocal /sanguo/shuguo.txt ./
  • -get:等同于copyToLocal,生产环境更习惯用get
 [atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -get /sanguo/shuguo.txt ./shuguo2.txt

直接操作

 -ls: 显示目录信息
 [atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -ls /sanguo
 ​
 -cat:显示文件内容
 [atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -cat /sanguo/shuguo.txt
 ​
 -chgrp、-chmod、-chown:Linux文件系统中的用法一样,修改文件所属权限
 [atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs  -chmod 666  /sanguo/shuguo.txt
 [atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs  -chown  atguigu:atguigu   /sanguo/shuguo.txt
 ​
 -mkdir:创建路径
 [atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -mkdir /jinguo
 ​
 -cp:从HDFS的一个路径拷贝到HDFS的另一个路径
 [atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -cp /sanguo/shuguo.txt /jinguo
 ​
 -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
 ​
 -tail:显示一个文件的末尾1kb的数据
 [atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -tail /jinguo/shuguo.txt
 ​
 -rm:删除文件或文件夹
 [atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -rm /sanguo/shuguo.txt
 ​
 -du统计文件夹的大小信息
 [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
 说明:27表示文件大小;81表示27*3个副本;/jinguo表示查看的目录
 ​
 -setrep:设置HDFS中文件的副本数量
 [atguigu@hadoop102 hadoop-3.1.3]$ hadoop fs -setrep 10 /jinguo/shuguo.txt
 ​
 # 注:这里设置的副本数只是记录在NameNode的元数据中,是否真的会有这么多副本,还得看DataNode的数量。
 # 因为目前只有3台设备,最多也就3个副本,只有节点数增加到10台时,副本数才能达到10。

7 HDFS 的API操作

7.1客户端环境准备

  • 找到资料包路径下的 Windos 依赖文件夹,拷贝 hadoop-3.1.0 到非中文路径(比如d:\)。
  • 配置 HADOOP_HOME 环境变量
  • 配置 Path 环境变量

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

  • 在IDEA中创建一个Maven工程 HdfsClientDemo,并导入相应的依赖坐标+日志添加
 <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,内容如下
 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.atguigu.hdfs
  • 创建 HdfsClient 类
 public class HdfsClient {
     @Test
     public void testMkdirs() throws IOException, URISyntaxException, InterruptedException {

         // 1 获取文件系统
         Configuration configuration = new Configuration();

         // FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:8020"), configuration);
         FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:8020"), configuration,"atguigu");

         // 2 创建目录
         fs.mkdirs(new Path("/xiyou/huaguoshan/"));

         // 3 关闭资源
         fs.close();
     }
 }
  • 执行程序 客户端去操作 HDFS 时,是有一个用户身份的。默认情况下,HDFS客户端 API 会采用 Windows 默认用户访问 HDFS,会报权限异常错误。所以在访问HDFS时,一定要配置用户。
 org.apache.hadoop.security.AccessControlException: Permission denied: user=56576, access=WRITE, inode="/xiyou/huaguoshan":atguigu:supergroup:drwxr-xr-x

7.2HDFS 的API案例操作

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

  • 编写源代码
 @Test
 public void testCopyFromLocalFile() throws IOException, InterruptedException, URISyntaxException {
     // 1 获取文件系统
     Configuration configuration = new Configuration();
     configuration.set("dfs.replication", "2");
     FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:8020"), configuration, "atguigu");
 ​
     // 2 上传文件
     fs.copyFromLocalFile(new Path("d:/sunwukong.txt"), new Path("/xiyou/huaguoshan"));
 ​
     // 3 关闭资源
     fs.close();
 }
  • 将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>
  • 参数优先级

参数优先级排序:(1)客户端代码中设置的值 >(2)ClassPath下的用户自定义配置文件 >(3)然后是服务器的自定义配置(xxx-site.xml) >(4)服务器的默认配置(xxx-default.xml)

HDFS文件下载

 @Test
 public void testCopyToLocalFile() throws IOException, InterruptedException, URISyntaxException{
     // 1 获取文件系统
     Configuration configuration = new Configuration();
     FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:8020"), configuration, "atguigu");
     
     // 2 执行下载操作
     // boolean delSrc 指是否将原文件删除
     // Path src 指要下载的文件路径
     // Path dst 指将文件下载到的路径
     // boolean useRawLocalFileSystem 是否开启文件校验
     fs.copyToLocalFile(false, new Path("/xiyou/huaguoshan/sunwukong.txt"), new Path("d:/sunwukong2.txt"), true);
     
     // 3 关闭资源
     fs.close();
 }

HDFS文件更名和移动

 @Test
 public void testRename() throws IOException, InterruptedException, URISyntaxException{
   // 1 获取文件系统
   Configuration configuration = new Configuration();
   FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:8020"), configuration, "atguigu"); 
     
   // 2 修改文件名称
   fs.rename(new Path("/xiyou/huaguoshan/sunwukong.txt"), new Path("/xiyou/huaguoshan/meihouwang.txt"));
     
   // 3 关闭资源
   fs.close();
 }

HDFS删除文件和目录

 @Test
 public void testDelete() throws IOException, InterruptedException, URISyntaxException{
   // 1 获取文件系统
   Configuration configuration = new Configuration();
   FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:8020"), configuration, "atguigu");
     
   // 2 执行删除
   fs.delete(new Path("/xiyou"), true);
     
   // 3 关闭资源
   fs.close();
 }

HDFS文件详情查看

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

 @Test
 public void testListFiles() throws IOException, InterruptedException, URISyntaxException {
   // 1获取文件系统
   Configuration configuration = new Configuration();
   FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:8020"), configuration, "atguigu");
 ​
   // 2 获取文件详情
   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 关闭资源
   fs.close();
 }

文件和文件夹判断

 @Test
 public void testListStatus() throws IOException, InterruptedException, URISyntaxException{
     // 1 获取文件配置信息
     Configuration configuration = new Configuration();
     FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:8020"), configuration, "atguigu");
 ​
     // 2 判断是文件还是文件夹
     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());
         }
     }
     
     // 3 关闭资源
     fs.close();
 }