HDFS-基础入门必知必会

367 阅读8分钟

本文内容均来自于尚硅谷Hadoop3.0课程,感兴趣的同学可以在B站找到官方的视频教程哈

1、概述

1.1、产生背景和定义

  • 背景:一个节点无法装下所有的数据,因此将大数据分散到不同节点上存储,需要分布式文件管理系统管理这些分布式文件,HDFS就是分布式文件管理系统的一种实现。
  • 定义:分布式文件管理系统,通过目录树定位文件
  • 使用场景:单词写入,多次读取(无法update已经上传的数据,只能append)

1.2、优缺点

  • 高容错性

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

    • 数据规模GB、TB、甚至PB
    • 文件规模能够高达百万以上
  • 构建在廉价机器上,通过多副本机制,提高可靠性

  • 不适合低延迟数据访问,比如毫秒级别访问

  • 无法高效对大量小文件存储,NameNode(内存中)会存储文件目录和块信息,大量小文件说明内存中将会存储大量文件目录和块信息,不可取。小文件的寻址时间超过读取时间。

  • 不支持并发写入一个文件。仅支持append,不支持update

1.3、组成

  • 官网架构图

image.png

  • NameNode(NN):就是master,管理datanode集群信息

    • 管理HDFS的名称空间、副本策略(一主多从类似的)、数据块的映射信息(某些数据块在某个datanode上),处理客户端读写请求
  • DataNode(DN):就是slaver,存储数据、执行读写IO操作

  • client:客户端

    • 文件切分,文件上传HDFS的时候,Client将文件切分成一个一个的Block,然后进行上传
    • 与NN交互,获取DN地址
    • 与DN进行IO交互
    • Client提供一些命令来管理HDFS,比如NameNode格式化
    • Client可以通过一些命令来访问HDFS,比如对HDFS增删查改操作
  • Second NameNode(2NN):并非NameNode的热备。当NameNode挂掉的时候,它并不能马上替换NameNode并提供服务。

    • 辅助NameNode,分担其工作量,比如定期合并Fsimage(镜像文件)和Edits,并推送给NameNode;
    • 在紧急情况下,可辅助恢复NameNode(仅能恢复一部分数据)。

1.4、文件块大小

HDFS中的文件在物理上是分块存储,块大小可通过dfs.blocksize参数设置,2/3版本后默认128M。

寻址时间为传输时间的1%最佳:寻址时间10ms,传输时间1s,磁盘传输效率大约100M/s,因此设置128M差不多

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

  • 块太小,则相对块的数量非常多,寻址时间增加
  • 块太大,传输时间则增加,同时处理数据非常耗时

HDFS块的大小设置主要取决于磁盘传输速率。

2、HDFS的shell操作

hadoop fs OP === hdfs dfs OP 大部分命令和Linux很像,例如mkdir、ls、cat等

  • 帮助命令
# hadoop fs -help op
hadoop fs -help mkdir

2.1、上传

  • -moveFromLocal:本地文件剪切至HDFS
# hadoop fs -moveFromLocal 本地文件路径 hdfs文件路径
hadoop fs -moveFromLocal ./test.txt /test
  • -copyFromLocal:本地文件拷贝至HDFS
# hadoop fs -copyFromLocal 本地文件路径 hdfs文件路径
hadoop fs -copyFromLocal ./test.txt /test
  • -put:等同于-copyFromLocal
  • -appendToFile:将本地文件追加至HDFS文件上
# hadoop fs -appendToFile 本地文件路径 hdfs文件路径
hadoop fs -appendToFile ./test.txt /test

2.2、下载

  • -copyToLocal:从HDFS拷贝至本地
# hadoop fs -copyToLocal hdfs文件路径 本地文件路径
hadoop fs -copyToLocal /test/test.txt ./
  • -get:等同于-copyToLocal

3、HDFS的API操作

API参考:hadoop.apache.org/docs/r3.1.3…

3.1、客户端创建

URI uri = new URI("hdfs://hadoop100:8020");
// 配置参数优先级:hdfs-default.xml => hdfs-site.xml => 在项目资源目录下的配置文件 => 代码里面的配置
Configuration configuration = new Configuration();
configuration.set("dfs.replication", "2");
String user = "chub";
FileSystem fs = FileSystem.get(uri, configuration, user);

3.2、常用API

  • 创建目录
fs.mkdirs(new Path("/dir/subdir1"));
  • 上传文件
// 参数解读:参数一:表示删除原数据; 参数二:是否允许覆盖;参数三:原数据路径; 参数四:目的地路径
fs.copyFromLocalFile(false, true, new Path("D:\test.txt"), new Path("hdfs://hadoop100/dir/subdir1"));

FSDataOutputStream fos = fs.create(new Path("/input"));
fos.write("hello world".getBytes());
  • 下载文件
// 参数的解读:参数一:原文件是否删除;参数二:原文件路径HDFS; 参数三:目标地址路径Win ; 参数四:
//fs.copyToLocalFile(true, new Path("hdfs://hadoop100/dir/subdir1/"), new Path("D:\"), true);
fs.copyToLocalFile(false, new Path("hdfs://hadoop100/test.txt"), new Path("D:\"), false);
  • 文件删除
// 参数解读:参数1:要删除的路径; 参数2 : 是否递归删除
// 删除文件
fs.delete(new Path("/jdk-8u212-linux-x64.tar.gz"), false);
// 删除空目录
fs.delete(new Path("/dir2"), false);
// 删除非空目录
fs.delete(new Path("/dir"), true);
  • 文件rename和移动
// 参数解读:参数1 :原文件路径; 参数2 :目标文件路径
// 对文件名称的修改
fs.rename(new Path("/dir/test.txt"), new Path("/dir/test1.txt"));

// 文件的移动和更名
fs.rename(new Path("/dir/test.txt"), new Path("/dir2/test1.txt"));

// 目录更名
fs.rename(new Path("/dir"), new Path("/dir1"));
  • 获取文件详情
// 获取所有文件信息
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));
}
  • 判断文件或者文件夹
FileStatus[] listStatus = fs.listStatus(new Path("/"));
for (FileStatus status : listStatus) {
    if (status.isFile()) {
        System.out.println("文件:" + status.getPath().getName());
    } else {
        System.out.println("目录:" + status.getPath().getName());
    }
}

4、HDFS的读写流程

4.1、HDFS的写数据流程

  • 客户端侧:创建HDFS客户端(Distributed FileSystem)

  • NameNode侧:检查目录树是否可以创建文件

    • 检查权限
    • 检查目录结构(目录是否存在)
  • NN侧:响应允许上传文件

  • 客户端侧:请求DN节点地址

  • NN侧:返回DN节点地址(返回最近节点距离的节点)

  • 客户端侧:创建数据流,向某一个DN节点建立连接,然后该DN节点与其它DN节点建立连接,传输数据

image (1).png

4.2、网络拓扑-节点距离计算

HDFS写入数据时,会将数据上传至最近节点距离的DN,这个距离的计算方式如下:

节点距离:两个节点到达最近的共同祖先的距离总和。

  • 同一节点上的进程 = 0
  • 同一机架上的不同节点 = 2
  • 同一数据中心不同机架上的节点 = 4
  • 不同数据中心的节点 = 6

image (2).png

4.3、机架感知(副本节点选择)

第一个副本在Client所处的节点上。如果客户端在集群外,随机选一个。

第二个副本在另一个机架的随机一个节点

第三个副本在第二个副本所在机架的随机节点

4.4、HDFS读数据流程

  • 客户端侧:创建HDFS客户端(Distributed FileSystem)
  • 客户端侧:请求下载文件
  • NN侧:返回目标文件的元数据信息
  • 客户端侧:创建数据流,根据节点距离节点的当前负载能力选择读取的节点

image (3).png

5、NN和2NN的工作机制

fsimage文件:镜像文件,主要保存元数据信息

edits文件:镜像文件的操作记录文件,存储的是对镜像文件的操作记录。类似Redis中的AOF

5.1、NN和2NN工作原理

NN启动后会加载fsimage和edits到内存中。每次有元数据修改,首先写edits文件,记录操作步骤。然后2NN会同步edits和fsimage,生成新的fsimage文件,该文件的元数据是包含启动后的元数据+启动后更新的步骤。最后将新生成的fsimage同步至NN上。保证内存中的数据为最新的。

image (4).png

5.2、fsimage和edits解析

Fsimage文件:HDFS文件系统元数据的一个永久性的检查点,其中包含HDFS文件系统的所有目录和文件inode的序列化信息。

Edits.文件:存放HDFS文件系统的所有更新操作的路径,文件系统客户端执行的所有写操作首先 会被记录到Edits文件中。

seen_txid文件保存的是一个数字,就是最后一个edits的数字

每次NameNode启动的时候都会将Fsimage文件读入内存,加载Edits里面的更新操作,保证内存中的元数据信息是最新的、同步的,可以看成NameNode启动的时候就将Fsimagei和Edits文件进行了合并。

  • 查看Fsimage文件

通过如下命令可以解析fsimage镜像文件

hdfs oiv -p 文件类型 -i 镜像文件 -o 转换后文件输出路径
  • 查看edits文件

通过如下命令可以解析edits文件

hdfs oev -p 文件类型 -i 编辑日志 -o 转换后文件输出路径
  • checkpoint时间设置

通常情况下,2NN每隔1小时进行checkpoint一次,同步edits和fsimage。

dfs.namenode.checkpoint.period 参数可设置

通常情况下,2NN每当操作次数达到1百万时,执行一次checkpoint

dfs.namenode.checkpoint.txns 参数可设置

默认情况下,2NN每隔60s检查NN的操作次数

dfs.namenode.checkpoint.check.period 参数可设置

6、DN工作机制

DN启动后,向NN注册

注册成功,NN保存DN元数据

DN每隔6h向NN上报数据块信息、每隔3s上报心跳。同时心跳会携带NN给DN的命令。

NN在10min+30s内没有收到DN心跳,认为DN已下线

6.1、DN数据完整性

  • 当DataNode读取Block的时候,它会计算CheckSum
  • 如果计算后的CheckSum,与Block创建时值不一样,说明Block已经损坏。
  • Client读取其他DataNode上的Block
  • 常见的校验算法crc(32),md5(128),sha1(160)
  • DataNode在其文件创建后周期验证CheckSum。