系统架构
物理架构-
Namenode 主要是记录数据存储的信息(类似目录)
-
Datanode 主要是记录数据(目录对应的内容)
逻辑架构 -
HDFS 由3个组件构成
- NameNode (内存中, 与SecondaryNameNode对应)
- SecondaryNameNode (持久化NameNode的数据到本地磁盘,单并不是 NameNode的备份)
- DataNode
NameNode
- 管理这文件系统命名空间
- 维护着文件系统树及书中的文件和目录,例如数据存在哪个datanode,存在datanode的那个block上面
- NameNode也负责维护所有这些文件或目录的打开、关闭、移动、重命名等操作
- 存储元数据
- 文件名目录名及它们之间的层级关系
- 文件目录的所有者及其权限
- 每个文件块的名及文件有哪些块组成
- 元数据保存在内存中
- Namenode元信息并不包含每个块的位置信息
- 保存文件, block, datanode之间的映射关系
- 文件名到block
- block到datanode
对于实际文件数据的保存与操作,都是由DataNode负责。当一个客户端请求数据时,它仅仅是从NameNode中获取文件的元信息,而具体的数据传输不需要经过NameNode,是由客户端直接与相应的DataNode进行交互。
需要注意的是,NameNode元信息并不包含每个块的位置信息,这些信息会在NameNode启动时从各个DataNode获取并保存在内存中,因为这些信息会在系统启动时由数据节点重建。把块位置信息放在内存中,在读取数据时会减少查询时间,增加读取效率。NameNode也会实时通过心跳机制和DataNode进行交互,实时检查文件系统是否运行正常。不过NameNode元信息会保存各个块的名称及文件由哪些块组成。
-
元信息的持久化
- 在NameNode中存放元信息的文件是 fsimage。在系统运行期间所有对元信息的操作都保存在内存中并被持久化到另一个文件edits中。并且edits文件和fsimage文件会被SecondaryNameNode周期性的合并
-
其他问题
- 运行NameNode会占用大量内存和I/O资源,一般NameNode不会存储用户数据或执行MapReduce任务。
-
Hadoop只有一个NameNode,这也就导致了hadoop集群的单点故障问题。因此,对NameNode节点的容错尤其重要,hadoop提供了如下两种机制来解决:
- 将hadoop元数据写入到本地文件系统的同时再实时同步到一个远程挂载的网络文件系统(NFS)。
- 运行一个secondary NameNode,它的作用是与NameNode进行交互,定期通过编辑日志文件(editlogs)合并命名空间镜像(fsimage),当NameNode发生故障时它会通过自己合并的命名空间镜像副本来恢复。需要注意的是secondaryNameNode保存的状态总是滞后于NameNode,所以这种方式难免会导致丢失部分数据
SecondaryNameNode
- 需要注意,SecondaryNameNode并不是NameNode的备份
- 用来保存HDFS的元数据信息,比如命名空间信息,块信息等,由于这些信息是在内存中的,SecondnameNode是为了考虑持久化到磁盘
-
产生背景
NameNode启动过程.jpg
-- fsimage 在NameNode启动时对整个文件系统的快照
-- edit logs 在NameNode启动后,对文件系统的改动序列
-- fstime 保存了最后一个检查点的时间戳- NameNode一般不会进行重启,所以在运行过程中会产生大量的edit logs, 当NameNode挂掉或者需要重启时, 需要将fsimage跟editlogs 进行合并,这样的话就会耗费大量的时间,在这样的背景下产生了 SecondNameNode
-
SecondNameNode的作用
SecondNameNode的作用- 在文件系统中设置一个检查点来帮助NameNode更好的工作,不是要取代NameNode,也不是NameNode的备份
- 定时到NameNode去获取editLogs,并更新到fsimage中(SecondNameNode 自己的 fsimage)
- 一旦它有了新的fsimage文件,它将其拷贝到NameNode中(去替换NameNode中的fsimage)
- NameNode在下次重启时会使用这个新的fsimage,从而减少重启的时间
DataNode
NameNode和DataNode架构图- 负责存储数据块,负责为系统客户端提供数据块的读写服务
- 根据NameNode的指示进行创建,删除和复制的操作
- 心跳机制,定期报告文件块列表信息(NameNode更新元信息)
- DataNode之间进行通信, 块的副本处理(进行数据的备份,实现冗余)
- 数据块
- HDFS默认数据块大小64M
- 磁盘块(物理磁盘)一般为 512B(tune2fs -l 文件名 | grep Block 可以查看文件块大小)
- 原因: 块增大可以减少寻址时间,降低 寻址时间/文件传输时间,若寻址时间为10ms,磁盘传输速率为100MB/s, name该比例仅为 1%
- 数据块过大也不好,因为一个MapReduce通常以一个块作为输入,块过大会导致整体任务数量过小,降低作业处理速度
问题
-
Hadoop为什么喜欢大文件(为什么要跟NameNode放到一起讲)
- 一般来说,一条元信息记录会占用200byte内存空间。假设块大小为64MB,备份数量是3 ,那么一个1GB大小的文件将占用163=48个文件块。如果现在有1000个1MB大小的文件,则会占用10003=3000个文件块(多个文件不能放到一个块中,备份的话,只有其中的1000个可以放到一个机器的一个块上,别的需要放到不同的机器的不同的block上)。我们可以发现,如果文件越小,存储同等大小文件所需要的元信息就越多,而NameNode只有一个,所以,Hadoop更喜欢大文件。
-
SecondaryNameNode的作用和过程
- HDFS文件的元信息都保存在NameNode的内存中。在NameNode启动时,它首先会加载fsimage到内存中,在系统运行期间,所有对NameNode的操作也都保存在了内存中,同时为了防止数据丢失,这些操作又会不断被持久化到本地edits文件中。
- Edits文件存在的目的是为了提高系统的操作效率,NameNode在更新内存中的元信息之前都会先将操作写入edits文件。在NameNode重启的过程中,edits会和fsimage合并到一起,但是合并的过程会影响到Hadoop重启的速度,SecondaryNameNode就是为了解决这个问题而诞生的。
-
SecondaryNameNode定期合并edits和fsimage文件的过程步骤
- 合并之前告知NameNode把所有的操作写到新的edites文件并将其命名为edits.new。
- SecondaryNameNode从NameNode请求fsimage和edits文件
- SecondaryNameNode把fsimage和edits文件合并成新的fsimage文件
- NameNode从SecondaryNameNode获取合并好的新的fsimage并将旧的替换掉,并把edits用第一步创建的edits.new文件替换掉
- 更新fstime文件中的检查点
-
数据块过大或者过小会导致什么问题?
- 块过小,会导致寻址时间增加,这样导致整个时间过长
块增大可以减少寻址时间,降低 寻址时间/文件传输时间,若寻址时间为10ms,磁盘传输速率为100MB/s, name该比例仅为 1% - 数据块过大也不好,因为一个MapReduce通常以一个块作为输入,块过大会导致整体任务(Map)数量过小,降低作业处理速度
- 块过小,会导致寻址时间增加,这样导致整个时间过长
-
version文件
#Sun Dec 20 03:37:06 CST 2015
namespaceID=555938486
clusterID=CID-6d9c34e0-9d84-45be-8442-be73a03ddea8
cTime=0
storageType=NAME_NODE
blockpoolID=BP-391569129-10.6.3.43-1450226754562
layoutVersion=-59
-
namespaceID :是文件系统的唯一标识符,在文件系统首次格式化之后生成的
-
cTime :表示 NameNode 存储时间的创建时间,由于笔者我的 NameNode 没有更新过,所以这里的记录值为 0,以后对 NameNode 升级之后,cTime 将会记录更新时间戳
-
storageType :说明这个文件存储的是什么进程的数据结构信息(如果是 DataNode,storageType=DATA_NODE)
-
blockpoolID:是针对每一个 Namespace 所对应的 blockpool 的 ID,上面的这个 BP-391569129-10.6.3.43-1450226754562 就是在我的 nameserver1 的 namespace下的存储块池的 ID,这个 ID 包括了其对应的 NameNode 节点的 ip 地址。
-
layoutVersion :表示 HDFS 永久性数据结构的版本信息, 只要数据结构变更,版本号也要递减,此时的 HDFS 也需要升级,否则磁盘仍旧是使用旧版本的数据结构,这会导致新版本的 NameNode 无法使用
-
clusterID :是系统生成或手动指定的集群 ID,在 -clusterid 选项中可以使用它;如下说明
使用如下命令格式化一个 Namenode:
$HADOOP_HOME/bin/hdfs namenode -format [-clusterId <cluster_id>]
选择一个唯一的 cluster_id,并且这个 cluster_id 不能与环境中其他集群有冲突。如果没有提供 cluster_id,则会自动生成一个唯一的 ClusterID。
使用如下命令格式化其他 Namenode:
HADOOP_PREFIX_HOME/bin/hdfs start namenode --config $HADOOP_CONF_DIR -upgrade -clusterId <cluster_ID>
如果没有提供 ClusterID,则会自动生成一个 ClusterID。
网友评论