HDFS介绍
条评论内容:HDFS介绍、HDFS原理
HDFS特点
1、典型的 Master/Slave 架构
NameNode是集群的主节点,DataNode是集群的从节点。
HDFS集群往往是一个NameNode(HA架构会有两个NameNode,联邦机制)+ 多个DataNode组成。
2、分块存储(block机制)
HDFS 中的文件在物理上是分块存储(block)的,块的大小可以通过配置参数来规定。
Hadoop2.x版本中默认的block大小是128M;
3、副本机制
为了容错,文件的所有 block 都会有副本。
每个文件的 block 大小和副本系数都是可配置的。应用 程序可以指定某个文件的副本数目。副本系数可以在文 件创建的时候指定,也可以在之后改变。 副本数量默认是3个。
4、一次写入,多次读出
HDFS 是设计成适应一次写入,多次读出的场景,且不支持文件的随机修改。支持追加写入,不支持随机更新
正因为如此,HDFS 适合用来做大数据分析的底层存储服务,并不适合用来做网盘等应用(修改不 方便,延迟 大,网络开销大,成本太高)
HDFS架构
- 客户端:
- 上传文件到HDFS的时候,Client负责将文件切分成Block,然后进行上传
- 请求NameNode交互,获取文件的位置信息
- 读取或写入文件,与DataNode交互
- Client可以使用一些命令来管理HDFS或者访问HDFS
- NameNode:
- 维护管理Hdfs的名称空间(NameSpace)
- 维护副本策略
- 记录文件块(Block)的映射信息
- 负责处理客户端读写请求
- DataNode:
- 保存实际的数据块
- 负责数据块的读写
- SecondaryNameNode
- 备份NameNode中的元数据信息
- 提高NameNode的重启速度
- 必要的时候可作为新的NameNode
HDFS命令
执行位置:$HADOOP_HOME/bin
命令头:hdfs dfs\hadoop fs
常用命令:
1 | -- 查看目录:hadoop fs -ls / |
HDFS重要概念
block
HDFS3.x上的文件会按照128M为单位切分成一个个的block,分散存储在集群的不同的数据节点datanode上,需要注意的是,这个操作是HDFS自动完成的
机架存储策略
实际机房中,会有若干机架,每个机架上会有若干台服务器
一般来说我们会把一个block的3个副本分别按照下述方法进行存储:
第一个副本就存储在一个机架A上
第二个副本存储在和这个block块不同机架(比如机架B)的一个服务器上
第三个副本存储在机架B的另外一个服务器上(注意副本2,3都存储在了机架B)
1 | 我们存储第2个副本时会优先把副本存储在不同的机架上,这是为了防止出现一个机架断电的情况,如果副本也存储在同机架上的不同服务器上,这时候数据就可能丢失了。 |
HDFS读写流程
写流程
流程解析:
1 | --1.客户端调用HDFS的create方法 |
读流程
1 | --1.HDFS client调用文件系统的open方法 |
HDFS的元数据管理机制
元数据概述
HDFS元数据,按类型分,主要包括以下几个部分:
文件、目录自身的属性信息,例如文件名,目录名,修改信息等。
文件记录的信息的存储相关的信息,例如存储块信息,分块情况,副本个数等。
记录 HDFS 的 Datanode 的信息,用于 DataNode 的管理。
按形式分为内存元数据和元数据文件两种,分别存在内存和磁盘上。
HDFS 磁盘上元数据文件分为两类,用于持久化存储:
fsimage 镜像文件:是元数据的一个持久化的检查点,包含 Hadoop 文件系统中的所有目录和文件元数据信息,但不包含文件块位置的信息。文件块位置信息只存储在内存中,是在 datanode 加入集群的时候,namenode 询问 datanode 得到的,并且间断的更新。
Edits 编辑日志:存放的是 Hadoop 文件系统的所有更改操作(文件创建,删除或修改)的日志,文件系统客户端执行的更改操作首先会被记录到 edits 文件中。
1 | fsimage 和 edits 文件都是经过序列化的,在 NameNode 启动的时候,它会将 fsimage文件中的内容加载到内存中,之后再执行 edits 文件中的各项操作,使得内存中的元数据和实际的同步,存在内存中的元数据支持客户端的读操作,也是最完整的元数据。 |
NameNode 维护整个文件系统元数据。因此,元数据的准确管理,影响着 HDFS 提供文件存储服务的能力。
元数据目录相关文件
在 Hadoop 的 HDFS 首次部署好配置文件之后,并不能马上启动使用,而是先要对文件系统进行格式化。需要在 NameNode(NN)节点上进行如下的操作:
1 | $HADOOP_HOME/bin/hdfs namenode –format |
在这里要注意两个概念,一个是文件系统,此时的文件系统在物理上还不存在;二就是此处的格式化并不是指传统意义上的本地磁盘格式化,而是一些清除与准备工作。
格式化完成之后,将会在$dfs.namenode.name.dir/current 目录下创建如下的文件结构,这个目录也正是 namenode 元数据相关的文件目录:
其中的 dfs.namenode.name.dir 是在 hdfs-site.xml 文件中配置的,默认值如下:
dfs.namenode.name.dir 属性可以配置多个目录,各个目录存储的文件结构和内容都完全一样,相当于备份,这样做的好处是当其中一个目录损坏了,也不会影响到 Hadoop 的元数据,特别是当其中一个目录是 NFS(网络文件系统 Network File System,NFS)之上,即使你这台机器损坏了,元数据也得到保存。
下面对$dfs.namenode.name.dir/current/目录下的文件进行解释。
VERSION
示例:
namespaceID=934548976
clusterID=CID-cdff7d73-93cd-4783-9399-0a22e6dce196
cTime=0
storageType=NAME_NODE
blockpoolID=BP-893790215-192.168.24.72-1383809616115
layoutVersion=-47
namespaceID/clusterID/blockpoolID
这些都是 HDFS 集群的唯一标识符。标识符被用来防止 DataNodes 意外注册到另一个集群中的 namenode 上。这些标识在联邦(federation)部署中特别重要。联邦模式下,会有多个 NameNode 独立工作。每个的 NameNode 提供唯一的命名空间(namespaceID),并管理一组唯一的文件块池(blockpoolID)。clusterID 将整个集群结合在一起作为单个逻辑单元,在集群中的所有节点上都是一样的。
storageType
说明这个文件存储的是什么进程的数据结构信息(如果是 DataNode,storageType=DATA_NODE)
cTime
NameNode 存储系统创建时间,首次格式化文件系统这个属性是 0,当文件系统升级之后,该值会更新到升级之后的时间戳;
layoutVersion
表示 HDFS 永久性数据结构的版本信息,是一个负整数。
补充说明:
格式化集群的时候,可以指定集群的 cluster_id,但是不能与环境中其他集群有冲突。
如果没有提供 cluster_id,则会自动生成一个唯一的 ClusterID。1
$HADOOP_HOME/bin/hdfs namenode -format -clusterId <cluster_id>
seen_txid
$dfs.namenode.name.dir/current/seen_txid 非常重要,是存放 transactionId 的文件,format 之后是 0,它代表的是 namenode 里面的 edits_*文件的尾数,namenode 重启的时候,会按照 seen_txid 的数字,循序从头跑 edits_0000001~到 seen_txid 的数字。所以当你的 hdfs 发生异常重启的时候,一定要比对 seen_txid 内的数字是不是你 edits 最后的尾数。
Fsimage & edits
$dfs.namenode.name.dir/current 目录下在 format 的同时也会生成 fsimage 和 edits文件,及其对应的 md5 校验文件。
SecondaryNamenode的作用
NameNode 职责是管理元数据信息,DataNode 的职责是负责数据具体存储,那么SecondaryNameNode 的作用是什么?对很多初学者来说是非常迷惑的。它为什么会出现在HDFS 中。从它的名字上看,它给人的感觉就像是 NameNode 的备份。但它实际上却不是。
大家猜想一下,当 HDFS 集群运行一段事件后,就会出现下面一些问题:
edit logs 文件会变的很大,怎么去管理这个文件是一个挑战。
NameNode 重启会花费很长时间,因为有很多改动要合并到 fsimage 文件上。
如果 NameNode 挂掉了,那就丢失了一些改动。因为此时的 fsimage 文件非常旧。
因此为了克服这个问题,我们需要一个易于管理的机制来帮助我们 减小 edit logs 文件的大小和得到一个最新的fsimage 文件,这样也会减小在 NameNode 上的压力。这跟Windows 的恢复点是非常像的,Windows 的恢复点机制允许我们对 OS 进行快照,这样当系统发生问题时,我们能够回滚到最新的一次恢复点上。
SecondaryNameNode 就是来帮助解决上述问题的,它的职责是合并 NameNode 的 editlogs 到 fsimage 文件中。
Checkpoint
每达到触发条件,会由 secondary namenode 将 namenode 上积累的所有 edits 和一个最新的 fsimage 下载到本地,并加载到内存进行 merge(这个过程称为 checkpoint),如下图所示:
Checkpoint 触发条件
Checkpoint 操作受两个参数控制,可以通过 core-site.xml 进行配置:
1 | <property> |
Checkpoint 详细步骤
NameNode 管理着元数据信息,其中有两类持久化元数据文件:edits 操作日志文件和fsimage 元数据镜像文件。新的操作日志不会立即与 fsimage 进行合并,也不会刷到NameNode 的内存中,而是会先写到 edits 中(因为合并需要消耗大量的资源),操作成功之后更新至内存。
有 dfs.namenode.checkpoint.period 和 dfs.namenode.checkpoint.txns 两个配置,只要达到这两个条件任何一个,secondarynamenode 就会执行 checkpoint 的操作。
当触发 checkpoint 操作时,NameNode 会生成一个新的 edits 即上图中的 edits.new 文件,同时 SecondaryNameNode 会将 edits 文件和 fsimage 复制到本地(HTTP GET 方式)。
secondarynamenode 将下载下来的 fsimage 载入到内存,然后一条一条地执行 edits 文件中的各项更新操作,使得内存中的 fsimage 保存最新,这个过程就是edits 和fsimage文件合并,生成一个新的 fsimage 文件即上图中的 Fsimage.ckpt 文件。
secondarynamenode 将新生成的 Fsimage.ckpt 文件复制到 NameNode 节点。
在 NameNode 节点的 edits.new 文件和 Fsimage.ckpt 文件会替换掉原来的 edits 文件和 fsimage 文件,至此刚好是一个轮回,即在 NameNode 中又是 edits 和 fsimage 文件。
等待下一次 checkpoint 触发 SecondaryNameNode 进行工作,一直这样循环操作。
从上面的描述我们可以看出,SecondaryNamenode 根本就不是 Namenode 的一个热备,其只是将 fsimage 和 edits 合并。其拥有的 fsimage 不是最新的,因为在他从 NameNode 下载 fsimage 和 edits 文件时候,新的更新操作已经写到 edit.new 文件中去了。而这些更新在 SecondaryNamenode 是没有同步到的!当然, 如果 NameNode 中的 fsimage 真的出问题了,还是可以用SecondaryNamenode 中的 fsimage 替换一下NameNode 上的 fsimage ,虽然已经不是最新的 fsimage ,但是我们可以将损失减小到最少!