HDFS 目标:
- 运用在大量廉价商用机器,提供容错机制
- 简单一致性模型:一次写入多次读取,支持追加,不允许修改,保证数据一致性
- 流式数据访问:批量读取而非随机读取,关注吞吐量而非时间
- 存储大规模数据集,典型文件大小单位为 GB 或 TB,关注横向线性扩展
优点:
- 高容错、高可用、高扩展
- 数据冗余多副本,副本丢失自动恢复
- NameNode HA(NameNode 高可用模式)、HDFS 安全模式
- 最大支持万台节点规模的集群
- 海量数据存储
- 构建成本低,安全可靠
- 适合大规模离线批处理
- 流式数据访问
- 数据位置暴露给计算框架
缺点:
- 不适合低延时数据访问
- 不适合大量小文件存储
- 元数据占用 NameNode 大量内存空间
- 磁盘寻道时间超过读取时间
- 不支持并发写入,一个文件同时只能拥有一个写入者
- 不支持文件随机修改,只支持追加写入
HDFS 架构
主从( Master / Slave )架构图:
ActiveStandbyClientDataNodeDataNodeDataNodeJournalNodeJournalNodeJournalNode
- NameNode 只负责管理,不负责存储业务数据
- DataNode 与 Client 交互,作数据交互
- DataNode 数据块默认大小为 128M,分散存储在各个 DataNode 上
- 副本数量默认为 3,所有文件均为副本(无主从之分)
- DataNode 每 3s 向 NameNode 发送心跳,包含数据块信息与节点容量信息
- 注:NameNode 与 DataNode 均为 java 进程,运行对应进程的节点就叫对应的节点
架构中的基本信息
NameNode
Active NameNode:
- 活动 Master 管理节点(集群中唯一)
- 管理命名空间
- 管理元数据:包含文件的位置、所有者、权限、数据块分布情况等
- 管理 Block 副本策略:默认 3 副本,多出的副本会自行删除,缺失的副本会自行复制
- 处理客户读写请求,为 DataNode分配任务
Standby NameNode:
- 热备 Master 管理节点。Hadoop 3.0 版本允许配置多个 Standby 节点
- Active NameNode 宕机后,快速升级为新的 Acitve NameNode
- 周期性同步 edits 编辑日志,定期合并 fsimage 与 edits 到本地磁盘
NameNode 元数据文件
- edits:保存了自最新检查点(checkpoint)之后的所有文件更新操作
- fsimage:保存了文件系统中所有的目录和文件信息(元数据检查节点镜像文件)
- Acitve NameNode 内存中的最新元数据为:fsimage + edits
- Standby NameNode 在检查点定期将内存中的元数据保存到 fsimage 中
元数据(Meta Data)
- 信息存放在 NameNode 内存中
包含:HDFS 中文件及目录的基本属性信息(如:拥有者、权限细腻下、创建时间等)、文件由哪些 Block 构成以及 Block 的位置存放信息 - 元数据信息持久化
- fsimage:元数据镜像检查点文件
- fsimage 文件是文件系统的元数据的持久检查点,文件名上会记录对应的 transaction Id
- 不会随文件系统的每个写操作而做持久化更新,因为写
- edits:编辑日志文件
- 文件系统执行写操作的时候,首先会被记录在 edit log 中
- 每个 edit log 文件通过前后缀记录当前操作的 transaction id
- 编辑日志会在每次写操作后但尚未将成功代码返回给客户段时同步刷新(先记到 edits,再同步到 fsimage,一段时间内达到 10w 条操作记录或者 1h 后同步 fsimage 信息
- 注:Block 的位置信息并不会做持久化,仅仅是在 DataNode 启动时汇报给 NameNode,存放在 NameNode 的内存空间中。
- fsimage:元数据镜像检查点文件
DataNode
DataNode 作用:
- slave 工作节点(可大规模扩展)
- 存储 Block 和数据校验
- 执行客户端发送的读写操作
- 通过心跳机制定期(默认 3s )向 NameNode 汇报运行状态和 Block 列表信息
- 集群启动时,DataNode 向 NameNode 提供 Block 列表信息
Block 数据块
- HDFS 最小存储单元
- 文件写入HDFS会被切分成若干个 Block
- Block 大小固定,默认 128MB,可自定义
- 若一个 Block 的大小小于设定值,不会占用整个快文件
- 默认情况下每个 Block 都有 3 副本
Client:
- 将文件切分为 Block
- 与 NameNode 交互,获取文件元数据
- 与 DataNode 交互,读取或写入数据
- 管理 HDFS
Block 存储:
- Block 是 HDFS 的最小存储单元
- 设置 Block 大小目的
- 最小化寻址开销,降低到 1% 左右
- 默认大小 128M(HDFS 1.x版本中默认 64M)
- 块太大:Map 任务数太少,作业执行速度变慢
- 块太小:寻址时间占比过高
- Block 与元数据分开存储:Block 存储于 DataNode,元数据存储于 NameNode
- Block 多副本
- 以 DataNode 节点为备份对象
- 默认副本数为 3
- 机甲感知:将副本存储到不同机架上,实现数据高容错率
- 副本均匀分布:提高访问带宽和读取性能,实现负载均衡
Block 文件:
- DataNode 在启动的时候自动创建存储目录,无需格式化
- DataNode 的 current 目录下的文件名都以 “blk_” 为前缀
- Block 元数据文件(*。meta)由一个包含版本信息、类型信息的头文件和一系列校验值组成
Block 副本放置策略:
- 副本 1:放置在 Client 所在节点
- 对于远程 Client,系统会选择随机节点
- 系统会优先选择空闲的 DataNode 节点
- 副本 2:放在不同的机架节点上
- 副本 3:放在与第 2 个副本同一机架不同节点上
- 副本 n:随机选择(同等条件下优先选择空闲节点)
JournalNode
JournalNode 作用:
- 同步 NameNode中的元数据
一、从 RAID 开始
大家都明白,大数据技术主要是要解决大规模数据的计算处理问题,但是我们要想对数据进行计算,首先要解决的其实是大规模数据的存储问题。当一个文件大小超过一张磁盘的大小的时候,我们该如何存储这个文件呢?在单机时代,主要的解决方式就是 RAID,而在分布式时代,主要的解决方案就是 HDFS。
无论是在单机时代还是分布式时代,大规模数据存储都需要解决以下三个核心问题:
- 数据存储容量的问题。既然大数据要解决的是数以 PB 计的数据计算问题,而一般的服务器磁盘容量通常 1~2TB,那么如何存储这么大规模的数据呢?
- 数据读写速度的问题。一般磁盘的连续读写速度为几十 MB,以这样的速度,几十 PB 的数据恐怕要读写到天荒地老。
- 数据可靠性的问题。磁盘大约是计算机设备中最易损坏的硬件了,通常情况一块磁盘使用寿命大概是一年,如果磁盘损坏了,数据怎么办?
在大数据技术出现之前,解决这些问题的办法就是使用 RAID 技术。
RAID 技术将多块普通磁盘组成一个阵列,共同对外提供服务。主要是为了改善磁盘的存储容量、读写速度,增强磁盘的可用性和容错能力。其中主流的 RAID 技术有以下几种,让我们来简单说说这几种 RAID 存储的区别。
- RAID 0:假设目前机器有 N 块磁盘,RAID 0 是数据在从内存缓冲区写入磁盘时,根据磁盘数量将数据分成 N 份,这些数据同时并发写入 N 块磁盘,使得数据整体写入速度是一块磁盘的 N 倍;读取的时候也一样,因此 RAID 0 具有极快的数据读写速度。但是 RAID 0 不做数据备份,N 块磁盘中只要有一块损坏,数据完整性就被破坏,其他磁盘的数据也都无法使用了。
- RAID 1:RAID 1 是数据在写入磁盘时,将一份数据同时写入两块磁盘,这样任何一块磁盘损坏都不会导致数据丢失,插入一块新磁盘就可以通过复制数据的方式自动修复,具有极高的可靠性。
- RAID 10:如图所示,RAID 10 就是将 RAID 1 和 RAID 0 结合的产物,它将 N 块磁盘平均分成两个部分,在每一份磁盘里利用 RAID 0 的并发读写,这样子既能提高可靠性又能改善性能。
- RAID 5:RAID 5 与 RAID 1 类似,但 RAID 5 中添加了校验数据块 P,当其中任意一块磁盘损坏时,都可以使用校验块 P 进行修复。
- RAID 6:RAID 6 与 RAID 5 类似,但是数据只写入 N-2 块磁盘,并螺旋式地在两块磁盘中写入校验信息(使用不同算法生成)。
从下面表格可以看出在相同磁盘数目(N)的情况下,各种 RAID 技术的比较
现在,让我们回过头来,解析下 RAID 技术如何解决在文章开始提到的三个核心问题
- 数据存储容量的问题。RAID 使用了 N 块磁盘构成一个存储阵列,如果使用 RAID 5,数据就可以存储在 N-1 块磁盘上,这样将存储空间扩大了 N-1 倍。
- 数据读写速度的问题。RAID 根据可以使用的磁盘数量,将待写入的数据分成多片,并发同时向多块磁盘进行写入,显然写入的速度可以得到明显提高;同理,读取速度也可以得到明显提高。不过,需要注意的是,由于传统机械磁盘的访问延迟主要来自于寻址时间,数据真正进行读写的时间可能只占据整个数据访问时间的一小部分,所以数据分片后对 N 块磁盘进行并发读写操作并不能将访问速度提高 N 倍。
- 数据可靠性的问题。使用 RAID 10、RAID 5 或者 RAID 6 方案的时候,由于数据有冗余存储,或者存储校验信息,所以当某块磁盘损坏的时候,可以通过其他磁盘上的数据和校验数据将丢失磁盘上的数据还原。
二、HDFS 大驾光临
我们知道,Google 大数据“三驾马车”的第一驾是 GFS(Google 文件系统),而 Hadoop 的第一个产品是 HDFS,可以说分布式文件存储是分布式计算的基础,也可见分布式文件存储的重要性。如果我们将大数据计算比作烹饪,那么数据就是食材,而 Hadoop 分布式文件系统 HDFS 就是烧菜的那口大锅。
Hadoop 分布式文件系统 HDFS 的设计目标是管理数以千计的服务器、数以万计的磁盘,将这么大规模的服务器计算资源当作一个单一的存储系统进行管理,对应用程序提供数以 PB 计的存储容量,让应用程序像使用普通文件系统一样存储大规模的文件数据。那么问题来了,我们该如何设计这样的一个分布式文件系统呢?
我们在前面提到,在单机中,我们采用 RAID 磁盘阵列来将数据分片后,在多块磁盘上并发进行数据读写,这样子既提高了存储容量,也加快了访问速度,并通过冗余校验提升了数据的可靠性。我们将 RAID 技术的设计理念扩大到整个分布式集群中,就产生了分布式文件系统。Hadoop 分布式文件系统的核心原理就是如此。
和 RAID 在多个磁盘上进行文件存储及并行读写的思路一样,HDFS 是在一个大规模分布式服务器集群上,对数据分片后进行并行读写及冗余存储。因为 HDFS 可以部署在一个比较大的服务器集群上,集群中所有服务器的磁盘都可供 HDFS 使用,所以整个 HDFS 的存储空间可以达到 PB 级容量。
上面的图是 HDFS 的架构图,从图中不难发现,HDFS 的关键组件有两个,分别为 DataNode 和 NameNode。
DataNode 负责文件数据的存储和读写操作,HDFS将文件分割成若干数据块(Block),每个 DataNode 存储一部分数据块,这样文件就分布存储在整个 HDFS 服务器集群中。应用程序客户端(Client)可以并行对这些数据块进行访问,从而使得 HDFS 可以在服务器集群规模上实现数据并行访问,极大地提高了访问速度。
NameNode 负责整个分布式文件系统的元数据(MetaData)管理,也就是文件路径名、数据块的 ID 以及存储位置等信息,相当于操作系统中文件分配表(FAT)的角色。HDFS 为了保证数据的高可用,会将一个数据块复制为多份(缺省情况为 3 份),并将多份相同的数据块存储在不同的服务器上,甚至不同的机架上。这样当有磁盘损坏,或者某个 DataNode 服务器宕机,甚至某个交换机宕机,导致其存储的数据块不能访问的时候,客户端会查找其备份的数据块进行访问。
下图为数据块多备份存储示意图,由图可以看出,文件 /hdfs_sample/part-0 有三份副本,其中存储的 BlockID 为 1,2。Block 1 的三个副本分别位于 DataNode0、DataNode1、DataNode2 三台服务器上,上述任意一台服务器宕机后,每个数据块都至少存在一个备份,因此不会影响对文件 /hdfs_sample/part-0 的访问。
NameNode(Filename,numReplicas,block-ids)/hdfs_sample/part-0,r:3,{1,2},/hdfs_sample/part-1,r:3,{3,4}DataNode 143224321413
和 RAID 一样,HDFS 也是将数据分成若干数据块后,存储到不同服务器上,从而实现数据大容量存储,并且不同分片的数据可以并行进行读 / 写操作,进而实现数据的高速访问。你可以看到,HDFS 的大容量存储和高速访问相对比较容易实现,但是 HDFS 是如何保证存储的高可用性呢?
接下来我们从不同层面探究下 HDFS 的高可用设计