除了对文件系统本身元数据的管理之外,NameNode还需要维护整个集群的机架及DataNode的信息、Lease管理以及集中式缓存引入的缓存管理等等。这几部分数据结构空间占用相对固定,且占用较小。
测试数据显示,Namespace目录和文件总量到2亿,数据块总量到3亿后,常驻内存使用量超过90GB。
DataNode负责存储和检索数据块,他受客户端和Namenode调度,并且他会定期向NameNode发送本节点上所存储的块列表,这就是为什么NameNode并不是永久保存各个节点块的信息原因了。
能看到NameNode的重要性,因为如果NameNode挂掉之后,无法根据DataNode上的数据重建文件。所以一般有两种机制进行对NameNode的容错。第一将NameNode上的元数据信息持久化到本地磁盘的同时,同时备份到一个挂载的远程网络文件系统上NFS。第二使用辅助NameNode,辅助NameNode会定期通过编辑日志合并镜像文件,防止编辑日志过大。但是他存在的问题在于总是滞后于NameNode的。所以一般可以将远程NFS的元数据复制到辅助NameNode上,辅助NameNode作为新的NameNode。
那么NameNode、DataNode、SecondaryNameNode存储结构是什么样子的呢。
NameNode存储结构:
{dfs.namenode.name.dir}|---VERSION
|---fsimage
|---edits
首先看下VERSION里面是什么
namespaceID:代表的是文件系统唯一标识,文件系统首次格式化时产生。没有注册到namenode之前的datanode都不知道namespaceID,所以可以通过这个来检查新建的datanode
clusterID:集群ID
cTime:NameNode存储系统创建时间,首次格式化文件系统这个属性是0,当文件系统升级之后,该值会更新到升级之后的时间戳
storageType:说明该存储目录是namenode的数据结构
layoutVersion:是一个负整数,用来描述HDFS持久化数据结构的版本的。这个版本与Haoop版本号无关,当文件系统布局发生改变他就回减一,但是此时HDFS也需要升级,否则新的namenode无法使用。
blockpoolID:是当前NameNode管理的数据块池ID,对于Federation HDFS,不同的NameNode管理不同的数据块池,同一个DataNode管理多个数据块池。blockpoolID的命名方式如下:
BP-<random num><namenode ip><namenode create time(UTC)> 在dn上会有这个桐木目录来存储数据
编辑日志和镜像文件
fsimage镜像文件存储着文件系统所有目录和文件的元数据信息即inode序列化信息。每一个inode是文件或目录的元数据内部描述方式,对于文件存储比如副本级别、修改时间、块大小等等。fsimage并不存储描述datanode的信息。因为datanode加入集群后会定期向namenode发送块的映射信息。
edits编辑日志如果这样会不断增长,这样每当重启namenode时候会比较慢,这时候文件系统就处于离线状态,这并不是用户想要的。可以通过运行辅助namenode来解决。
为主Namenode中的元数据创建检查点,进行编辑日志和镜像文件合并。
(1)辅助namenode要求主namenode停止使用edits文件,暂时使用新的edits文件。
(2)辅助namenode从主namenode那里获取fsimage和edits文件
(3)辅助namenode将fsimage加入到内存,然后根据edits执行文件操作,创建新的fsimage
(4)辅助namenode将新的fsimage发送到主namenode中
(5)主namenode用新的fsimage替代原先的fsimage,并且使用(1)中的eits代替旧的edits文件。
这就是为什么SecondaryNamenode也需要一台独立服务器的原因了。他的操作和namenode差不多
这个创建检查点需要两个配置控制,第一就是dfs.namenode.checkpoint.period属性设定,每隔多长时间创建一次检查点,默认是3600即一个小时。第二就是dfs.namenode.checkpoint.txns这个hadoop1中是fs.checkpoint.size,我在hadoop2.2中没有找到与之类似,但是估计是这个,当编辑日志达到这个配置的大小即使没有到达之前配置的时间也会创建检查点。
SecondaryNameNode中的current目录与namenode的一样,因为创建检查点不仅为主namenode创建检查点数据,也是辅助namenode也有一份检查点数据,用来备份namenode元数据,尽管他不是最新的。如果主namenode挂了,并且没有NFS,可以使用SecondaryNamenode作为主namenode,当dfs.namenode.name.dir中没有元数据的时候就会从dfs.namenode.checkpoint.dir中载入检查点数据。这就是为什么两者目录为什么设计成一样的原因了,不用担心覆盖现有的元数据。
DataNode的目录结构:
{dfs.datanode.data.dir}|--VERSION
|--BP-792156149-127.0.1.1-1431433217275
|--current
|--finalized
|--VERSION
VERSION内容与namenode类似,他的namespaceID是datanode首次向namenode访问获取的,storageID是每个datanode的id,namenode通过他来区分不同的datanode
看到BP-792156149-127.0.1.1-1431433217275这个让我明白了namendoe上面的那个blockpoolId了,这时hadoop1中没有的,在这个BP-792156149-127.0.1.1-1431433217275目录里面放着这个块池的current,里面还有一个VERSION这个VERSION才有namespaceID,而外层那个只有storageID
在hadoop2中数据块存放到块池中的finalized中以blk_为前缀,有两种类型:块文件和块文件元数据信息(以meta结尾)块文件存储数据,块文件信息存储版本号以及校验和等信息。
如果dfs.namenode.data.dir指定了不同磁盘的多个目录,数据会以轮转的方式写入到磁盘中,当同一个datanode不会存储相同的块。
dfsused:磁盘使用率
finalized 表示数据副本状态
块状态 |
存储目录 |
说明 |
Finalized |
${BP_HOME}/current/finalized |
表示该副本已经完成了所有数据的写入。 |
RBW |
${BP_HOME}/current/rbw |
表示该副本正在写入或追加数据。 |
RWR |
${BP_HOME}/current/rbw |
如果DataNode宕机或重启,处于RBW状态的副本将转换为RWR状态,不会在接受新数据的写入。 |
RUR |
${BP_HOME}/current/rbw |
当租约到期,NameNode将为客户端关闭其所占用的副本,这将使该副本进入RUR状态。 |
Temporary |
${BP_HOME}/tmp |
表示该副本正在被创建。 |
*${BP_HOME}为${datanode.data.dir}/current/<blockpool_id>
一个数据块由两个文件组成,一个为块数据文件(以blk_为前缀),一个为该数据块的元数据文件(以.meta为后缀),该文件包括了数据块的版本、类型和一系列区域检验和。当数据目录中的块文件达到64个之后,DataNode会在该目录下建立一个子目录(subdirn),将这些块文件移动到该目录下,以避免一个目录存储过多的文件,影响了系统的性能
如果你有时候连续格式化文件系统,会产生datanode与namenode 的namespaceID不同,这时候你启动不了datanode因为namenode并不认识这个datanode,你需要将datanode的namespaceID与namenode相匹配。
来源:https://www.cnblogs.com/ZFBG/p/11125068.html