大数据技术原理与应用 - (3). 分布式文件系统 HDFS

大数据技术原理与应用 - (3). 分布式文件系统 HDFS

【第二篇】 - 大数据存储与管理, 《大数据技术原理与应用, 林子雨》

本篇介绍大数据存储与管理相关技术的概念与原理,包括

Hadoop 分布式文件系统 (Hadoop Distributed File System, HDFS) 是真的 Google File System (GFS) 的开源实现,它是 Hadoop 两大核心组件之一,提供了在廉价服务器集群中进行大规模分布式存储的能力。

本章介绍分布式文件系统的基本概念、结构和设计需求,然后介绍 HDFS 的相关概念、体系结构、存储原理和读写过程。

分布式文件系统

分布式文件系统 (Distributed File System) 是一种通过网络实现文件在多台主机 (集群) 上进行分布式存储的文件系统。

计算机集群结构


计算机集群的基本架构
  • 分布式文件系统把文件分布存储到多个计算机节点(如上图节点 $x$ 和 $y$)上,成千上万的计算机节点构成计算机集群。
  • 每个机架可以放许多节点(计算机)。
  • 同一机架上的节点通过网络互联(常用吉比特以太网)。
  • 不同机架之间采用另一级(更快)网络活交换机互连。

分布式文件系统的结构

分布式文件系统在物理结构上是由计算机集群中的多个节点构成的,这些节点分为两类: 名称结点 (NameNode)数据节点 (DataNode)


大规模文件系统的整体架构

HDFS 简介


HDFS 架构

HDFS 是 Master/ Slave architecture (主从架构)。一个 HDFS 集群包括一个 NameNode,也就是一个 Master,和多个 DataNode,也就是 Slave。

在 HDFS 中,一个文件将会被拆分成多个 Block(blocksize 默认 128MB,也可以设置更高),这些 block 被存储在一系列 DataNodes 上。

典型的部署是一台专门的机器运行 NameNode,集群的其他机器运行 DataNode

A typical deployment has a dedicated machine that runs only the NameNode software. Each of the other machines in the cluster runs one instance of the DataNode software. The architecture does not preclude running multiple DataNodes on the same machine but in a real deployment that is rarely the case. [来源: Apache Hadoop 3.2.1 - HDFS Architecture 文档]

HDFS 要实现一下目标:

  • 兼容廉价的硬件设备
  • 流数据读写
  • 大数据集
  • 简单的文件模型
  • 强大的跨平台兼容性

HDFS 局限性:

  • 不适合低延迟数据访问。由于自身面向大规模数据批处理需求设计,高数据吞吐率同时意味着高响应延迟,因此不适合要求低延迟(实时反馈)的应用场景。
  • 无法高效存储大量小文件。小文件指大小远远小于一个 Block 大小(通常 128 MB)的文件。
    • NameNode 管理文件系统的 metadata,这些 metadata 保存在内存中,从而客户端能够快速获取文件实际存储位置。大量小文件意味着 NameNode 需要花大量的内存来保存这类大量小文件 metadata,大大降低了 metadata 的索引效率
    • 对于 MapReduce,大量小文件意味着会产生过多的 Map 任务,导致线程管理开销大大增加
    • 本身访问大量小文件的速度远远低于访问几个大文件的速度,因为需要不断从一个 DataNode 跳到另一个 DataNode。
  • 不支持多用户写入及任意修改文件。HDFS 只允许一个文件有一个写入者,且只允许对文件进行追加操作,不执行随机写操作。

HDFS 相关概念

HDFS 相关概念包括块 (Block), 名称节点 (NameNode), 数据节点 (DataNode), 第二名称节点 (Secondary NameNode)。

Block - 块

传统文件系统中,为了提高磁盘读写效率,一般采用数据块为单位,而非字节。

  • Hadoop 分布式文件系统 (HDFS) 与之区别与联系:

    • 联系:同样采用了数据的概念
    • 区别:为了最小化寻址开销,HDFS 的块比传统文件系统的块大。HDFS 默认一个块 64MB。
  • HDFS 采用抽象的块概念带来的好处:

    • 支持大规模文件存储:文件以块为单位进行存储,一个大规模文件可以被分拆成若干个文件块,不同的文件块可以被分发到不同的节点上,因此,一个文件的大小不会受到单个节点的存储容量的限制,可以远远大于网络中任意节点的存储容量
    • 简化系统设计:首先,大大简化了存储管理,因为文件块大小是固定的,这样就可以很容易计算出一个节点可以存储多少文件块;其次,方便了元数据的管理,元数据不需要和文件块一起存储,可以由其他系统负责管理元数据
    • 适合数据备份:每个文件块都可以冗余存储到多个节点上,大大提高了系统的容错性和可用性
  • Blocksize d的考虑:
    • 大 Block 的好处: 访问 HDFS 要三级寻址 (元数据目录、数据节点、从数据节点取数据)。设置大的块可以将寻址开销分摊到较多的数据中,降低了单位数据的寻址开销
    • 过大 Block 的坏处: 在后续 MapReduce 中 Map 任务一次只处理一个块中的数据,如果启动的 Map 任务太少,就降低了作业并行处理的速度

NameNode

  • NameNode (名称节点) 或称为 ‘主节点’ (Master Node)。
  • 负责文件和目录的创建、删除、重命名等。
  • 管理 DataNode 和文件块 (Block) 的映射关系。
  • 客户端只有访问 NameNode 才能请求 Block 的位置,进而读取相应数据。
  • NameNode 负责管理分布式文件系统的 NameSpace (命名空间),保存了两个核心的数据结果,即 FsImageEditLog
    • FsImage: 维护文件系统树和文件树中所有的文件和文件夹的 metadata。
    • EditLog: 记录所有针对文件的创建、删除、重命名等操作。

HDFS主要组件的功能

NameNode 启动过程和后续:

  1. 将 FsImage 的内容加载到内存当中,然后执行 EditLog 中的各项操作,使内存中的 metadata 保持最新。
  2. 步骤1. 完成后,会创建一个新的 FsImage 和 空的 EditLog (启动完成)
  3. NameNode 正常运作后,后续 HDFS 的更新操作会被写进 新的空的 EditLog 中。

DataNode

  • DataNode (数据节点) 或称为 ‘从节点’ (Slave Node)。
  • 负责数据的存储和读取。
    • 存储: 由 NameNode 分配存储位置,然后客户端直接写入相应的 DataNode
    • 读取: 客户端从 NameNode 获得 DataNode 和 Block 的映射关系,然后到相应位置访问 Block。
  • 定期向 NameNode 发送心跳信息,汇报自身及所有 block 信息,和健康状况;

数据冗余存储

HDFS 采用了多副本方式对数据进行冗余存储,保证了系统的容错性和可用性。一个数据块的多个副本会被分布到不同的 DataNode 上,如下图所示。


HDFS 数据块多副本存储

冗余存储好处:

  • 加快数据传输速度。当多个客户端需要同时访问同一个文件,可以让 Client 从不同的数据块中读取数据。
  • 容易检查数据错误。
  • 保证数据可靠性。单个 DataNode 故障不会导致数据丢失。

数据存取策略

存储

HDFS 默认的冗余复制因子是 3, i.e., 每个 block 会同时保存到 3 个 DataNode中。

  • 第一个副本,集群挑选一个磁盘不太满、Cpu 不太忙的 DataNode 存放。
  • 第二个副本,存放在相同机架 (rack) 上的不同 DataNode 中。
  • 第三个副本,存放在不同机架 (rack) 上的其他 DataNode 中。
  • 如果还有更多副本,随机选择 DataNode 存放。

读取

Client 优先选择在同一机架上的 DataNode 来读取数据块副本。如果数据块副本不在同一机架,则随机选择 DataNode 进行读取。

SecondaryNameNode

SecondaryNameNode (第二名称节点) 的功能

  1. 解决 EditLog 不断增大的问题
  2. 作为 NameNode 的冷备份

解决 EditLog 不断增大

SecondaryNameNode 定期对 EditLog 和 FsImage 进行合并操作,以减小 EditLog 文件大小,缩短 NameNode 重启时间。

第二名称节点工作过程示意图
  1. SecondaryNameNode 定期和 NameNode 通信,请求其停止使用 EditLog 文件,暂时将新的写操作写到一个新的文件 edit.new 上,这个操作是瞬间完成,上层写日志的函数完全感觉不到差别;
  2. SecondaryNameNode 通过 HTTP GET 方式从 NameNode 上获取到 FsImage 和 EditLog 文件,并下载到本地的相应目录下;
  3. SecondaryNameNode 将下载下来的 FsImage 载入到内存,然后一条一条地执行 EditLog 文件中的各项更新操作,使得内存中的 FsImage 保持最新;这个过程就是 EditLog 和 FsImage文件合并;
  4. SecondaryNameNode 执行完(3)操作之后,会通过 post 方式将新的 FsImage 文件发送到 NameNode 节点上
  5. NameNode 将从 SecondaryNameNode 接收到的新的 FsImage 替换旧的 FsImage 文件,同时将 edit.new 替换 EditLog 文件,通过这个过程EditLog就变小了

NameNode 冷备份

上述合并的过程可以看出,SecondaryNameNode 会定期执行合并操作得到新的 FsImage。从这个角度来看,SecondaryNameNode 相当于周期性地保存了 NameNode 中的 metadata 信息。

HDFS 体系结构

HDFS 命名空间管理

HDFS 的命名空间包含目录、文件、和块。命名空间管理是指命名空间支持对 HDFS 中的目录、文件和块做类似文件系统的创建、修改、删除等基本操作。

通信协议

所有 HDFS 通信协议都是构建在 TCP/IP 协议基础之上的。

  • 客户端 (Client) 通过一个可配置的端口向 NameNode 主动发起 TCP 链接,并使用客户端协议与 NameNode 交互。
  • 客户端与 DataNode 的交互通过 RPC (Remote Procedure Call) 来实现。

HDFS 数据读写过程

读数据

HDFS 读数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.io.BufferedReader;
import java.io.InputStreamReader ;
import org.apache.hadoop.conf.Configuration ;
import org.apache.hadoop.fs.FileSystem ;
import org.apache.hadoop.fs.Path ;
import org.apache.hadoop.fs.FSDataInputStream ;
public class Chapter3 {
public static void main(String[] args) {
try {
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
Path filename = new Path("hdfs://localhost:9000/user/hadoop/test.txt");
FSDataInputStream is = fs.open(filename);
BufferedReader d = new BufferedReader(new InputStreamReader(is));
String content = d.readLine(); //读取文件一行
System.out.println(content);
d.close(); //关闭文件
fs.close(); //关闭hdfs
} catch (Exception e) {
e.printStackTrace();
}
}
}

HDFS 读数据过程

写数据

HDFS 写数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.Path;
public class Chapter3 {
public static void main(String[] args) {
try {
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
byte[] buff = "Hello world".getBytes(); // 要写入的内容
String filename = "hdfs://localhost:9000/user/hadoop/test.txt"; //要写入的文件名
FSDataOutputStream os = fs.create(new Path(filename));
os.write(buff,0,buff.length);
System.out.println("Create:"+ filename);
} catch (Exception e) {
e.printStackTrace();
}
}
}

HDFS 写数据过程

HDFS 编程实现

常用 Shell 命令

  • 三种写法
    1. hadoop fs: 适用于任何不同的文件系统,比如本地文件系统和HDFS文件系统
    2. hadoop dfs: 只能适用于HDFS文件系统
    3. hdfs dfs: 只能适用于HDFS文件系统
HDFS 的 Shell 统一格式
1
hadoop fs [genericOptions] [commandOptions]
  • hadoop version: 打印 Hadoop 版本信息
  • hadoop fs -ls <path>: 显示 <path> 指定的文件的详细信息
  • hadoop fs -mkdir <path>: 创建 <path> 指定的文件夹
  • hadoop fs -cat <path>: 将 <path> 指定的文件的内容输出到标准输出 (stdout)
  • hadoop fs -tail [-f] <path>: 将 <path> 指定的文件最后 1KB 的内容输出到标准输出 (stdout)
  • hadoop fs -put <localsrc> <dest>: 将本地文件系统的 <localsrc> 复制到 Hadoop 文件系统。与 copyFromLocal 类似
  • hadoop fs -copyFromLocal <localsrc> <dest>: 将本地源文件 <localsrc> 复制到路径 <dest> 指定的文件或文件夹中
  • hadoop fs -get <src> <localdest>: 将 hadoop 文件系统的 <src> 复制到本地文件系统 <localdest>
  • hadoop fs -copyToLocal <hdfs source> <localdst>: 类似上面 getcopyFromLocal 相反
  • hadoop fs -chmod [-R] <mode> <path>: 将 <path> 指定的文件的权限更改为 <mode>。这个命令只适用于超级用户和文件的所有者。
  • hadoop fs -mv <src> <dest>: 将文件从源路径 <src> 移动到目标路径 <dest>
  • hadoop fs -cp <src> <dest>: 将文件从源路径 <src> 复制到目标路径 <dest>
  • hadoop fs -rm [-r] <path>: 删除 <path> 指定文件,只能删除空目录和文件,输入 -r 是递归删除

Comments

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×