HDFS概述及其API基本操作

1、HDFS概述

1.1 HDFS的意义

​ HDFS即Hadoop Distributed File System,是一种分布式文件系统,用于解决大数据的存储问题。

1.2 HDFS的使用场景

​ 适合一次写入,多次读出。

1.3 HDFS的优缺点

优点:

  • 高容错
    • 通过副本,提高容错性
    • 副本丢失,自动恢复
  • 适合处理大数据
    • 单个文件的数据规模大小
    • 文件数量规模
  • 构建在廉价的机器上,通过副本机制,提高可靠性、扩展性

缺点:

  • 不适合低延迟数据访问

    这主要受数据传输的带宽数据校验影响,需要消耗大量时间

  • 无法高效的对小文件进行存储

    一方面,元数据加载于NameNode节点的内存中。无论数据块的大小都会对应一个元数据,因此能存大的,不存小的;

    另一方面,存储过多的小文件会导致寻址时间超过读取时间,违反HDFS设计目标。

  • 不支持并发写入、文件随机修改。

    不允许多个线程同时写;

    仅支持追加,不支持随机修改;

1.4 HDFS组成架构

  • NameNode:主节点

    • 管理HDFS的名称空间NameSpace;在NameNode中的Namespace管理层是负责管理整个HDFS集群文件系统的目录树以及文件与数据块的映射关系。
    • 配置副本策略;
    • 管理数据块的映射信息;
    • 处理客户端读写请求。
  • DataNode:实际存储数据的节点

    • 存储实际的数据块;
    • 执行数据块的读/写操作。
  • Client

    • 文件切分;
    • 与NameNode交互
    • 与DataNode交互
    • Client提供一些命令管理HDFS
    • Client提供一些命令操作HDFS,如增删改查。
  • SecondaryNameNode:并非热备。

    • 辅助NameNode,分担其工作量;定期合并Fsimage和Edits,并推送给NameNode;
    • 在紧急情况下,可辅助恢复NameNode。

1.5 HDFS块大小

寻址时间为传输时间的1%最佳。如果寻址时间为10ms,那么传输所耗时间为1s最佳;而目前磁盘的速率普遍为100MB/s。因此规定块大小为128M。

  • 块设置太小,会导致寻址时间增加,寻址时间占比过高;
  • 块设置太大,导致磁盘传输数据的效率低下;
    另外,Map任务数太少,作业执行速度变慢。
    总结:HDFS块大小设置主要取决于磁盘传输速率

2、HDFS的API操作

2.1 基础环境

  1. 配置Hadoop3.1.0环境变量;

  2. 导入依赖

    <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>
    
    
  3. 在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
    

2.2 实操代码

无论什么客户端代码,例如jdbc hdfs kafka zookeeper;

  • 1.创建客户端对象
  • 2.使用客户端对象进行操作
  • 3.关闭客户端对象
package com.hpu.hadoop.hdfs;

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

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

public class HDFSClient {
    public static void main(String[] args) throws URISyntaxException, IOException, InterruptedException {
        //1.创建客户端对象
        Configuration configuration = new Configuration();
        URI uri = new URI("hdfs://hadoop102:8020");
//        URI uri = URI.create("hdfs://hadoop102:8020");
        FileSystem fileSystem = FileSystem.get(uri, configuration, "hadoop");

        //2.使用客户端对象进行操作
        fileSystem.mkdirs(new Path("/test"));

        //3.关闭客户端对象
        fileSystem.close();
    }
}
package com.hpu.hadoop.hdfs;

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

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.Arrays;

public class HDFS_Test {

    private FileSystem fileSystem;
    private Configuration configuration;

    @Before
    public void init() throws URISyntaxException, IOException, InterruptedException {
        configuration = new Configuration();
        configuration.set("dfs.replication","2");
        fileSystem = FileSystem.get(new URI("hdfs://hadoop102:8020"), configuration, "hadoop");
    }
    @After
    public void close() throws IOException {
        fileSystem.close();
    }

    @Test
    public void mkdir() throws IOException {
        fileSystem.mkdirs(new Path("/zyn/mkdirtest"));
    }

    @Test
    public void put() throws IOException {
        /**
         * 参数解读
         * boolean delSrc 是否删除源文件 windows本地
         * boolean overwrite 是否覆盖目标文件 hdfs
         * Path src  上传的文件路径  windows
         * Path dst  存放的文件路径  hdfs
         */
        fileSystem.copyFromLocalFile(false,true,new Path("E:\\smc.zip"),new Path("/zyn/mkdirtest/"));
    }
    @Test
    public void get() throws IOException {
        /**
         * 参数解读
         *   1.boolean delSrc 是否删除源文件
         *   2.Path src  源文件路径
         *   3.Path dst  目标文件路径
         *   4.boolean useRawLocalFileSystem 是否校验  true 不校验 false 校验
         */
        fileSystem.copyToLocalFile(false,new Path("/zyn/mkdirtest/smc.zip"),new Path("E:\\AAA\\a.zip"),true);
    }

    @Test
    public void mv() throws IOException {
        //文件的更名
        //fs.rename(new Path("/java/word.txt"),new Path("/java/1.txt"));
        //文件的移动
        //fs.rename(new Path("/java/1.txt"),new Path("/input"));
        //文件的更名且移动
        //fs.rename(new Path("/input/1.txt"),new Path("/java/word.txt"));
        //目录的更名
        //fs.rename(new Path("/java"),new Path("/linux"));
        //目录的移动
        //fs.rename(new Path("/linux"),new Path("/input"));
        //目录的更名且移动
        fileSystem.rename(new Path("/zyn/mkdirtest/1.zip"),new Path("/zyn/test/smc.zip"));
    }
    @Test
    public void rm() throws IOException {
        fileSystem.delete(new Path("/zyn"),true);
    }
    //查看文件的详情信息
    @Test
    public void ls() throws IOException {
        RemoteIterator<LocatedFileStatus> listFiles = fileSystem.listFiles(new Path("/"), true);
        while (listFiles.hasNext()) {
            LocatedFileStatus fileStatus = listFiles.next();
            System.out.println("------------"+fileStatus.getPath().getName()+"------------");
//            Permission	Owner	Group	Size	Last Modified	Replication	Block Size	Name
            System.out.println(fileStatus.getPermission());
            System.out.println(fileStatus.getOwner());
            System.out.println(fileStatus.getGroup());
            System.out.println(fileStatus.getLen());
            long time = fileStatus.getModificationTime();
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");
            System.out.println(format.format(time));
            System.out.println(fileStatus.getReplication());
            System.out.println(fileStatus.getBlockSize());
            BlockLocation[] blockLocations = fileStatus.getBlockLocations();
            System.out.println(Arrays.toString(blockLocations));
        }

    }
    @Test
    public void fileOrDir() throws IOException {
        FileStatus[] listStatus = fileSystem.listStatus(new Path("/"));
        for (FileStatus status : listStatus) {
            if (status.isFile()){
                System.out.println("f--"+status.getPath());
            } else if (status.isDirectory()){
                System.out.println("d--"+status.getPath());
            }
        }

    }


    public void fileOrDirRecursive(Path path) throws IOException {
        FileStatus[] listStatus = fileSystem.listStatus(path);
        for (FileStatus status : listStatus) {
            if (status.isFile()){
                System.out.println("f--"+status.getPath());
            } else if (status.isDirectory()){
                Path path1 = status.getPath();
                System.out.println("d--"+path1);

                fileOrDirRecursive(path1);
            }
        }
    }
    @Test
    public void testFDR() throws IOException {
        fileOrDirRecursive(new Path("/"));
    }

    //手动上传
    @Test
    public void putByIo() throws IOException {
        //1.输入流
        FileInputStream inputStream = new FileInputStream("E:\\smc.zip");
        //2.输出流
        FSDataOutputStream outputStream = fileSystem.create(new Path("/zy/smc.zip"));
        IOUtils.copyBytes(inputStream, outputStream,configuration);
        IOUtils.closeStreams(outputStream,inputStream);
    }
    @Test
    public void getByIo() throws IOException {
        //1.输入流
        FSDataInputStream inputStream = fileSystem.open(new Path("/zyn"));
        //2.输出流
        FileOutputStream fileOutputStream = new FileOutputStream("E:\\1.zip");
        //3.对拷
        IOUtils.copyBytes(inputStream,fileOutputStream,configuration);
        //4.关闭资源
        IOUtils.closeStreams(fileOutputStream,inputStream);
    }

}

注意事项:

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MelodyYN

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值