|
本文内容结构
本文从前提和设计目标、HDFS框架结构、HDFS可靠性保障机制、NAMENODE元数据目录结构介绍HDFS基本内容,并模拟了HDFS的几个场景将以上过程穿起来。
1.HDFS的前提及设计目标:
1.异常是常态
2.流式数据处理
3.大规模数据集
4.可移植性
5.移动计算而非移动数据
6.一致性(一写多读)
2.HDFS框架结构:
1.采用master/slave架构,即一个namenode(主),一组datanode(从)
2.HDFS文件系统支持以文件形式存储数据(传统数据库需要将数据按格式插入数据库),按典型块大小64M将数据文件分块,并尽可能分散的存放在datanodes上。
3.namenode管理hdfs文件系统,包括namespace(即目录结构)管理和block管理(其中包括 filename->blocks,block->datanode list的对应关系),目录结构和 blocks是以image和editlog文件持久保存在master上,block->datanode list对应关系不是持久保存,而是启动时通过DN的BLOCKREPORT获得并重建。所有这些信息就是HDFS系统的元数据。
4.datanode负责实际的底层的文件的读写,如果客户端client程序发起了读hdfs上的文件的命令,那么namenode首先获得FILE对应的所有block,然后告知client这些block数据是存储在那些dn上的,之后,client将直接和dn交互。
5.HDFS读 :客户端访问namenode获取FILE->BLOCK及BLOCK->DATANODE LIST->客户端取出第一个BLOCK->客户端连接存储该BLOCK最近的一个 DATANODE读取数据块->重复上两步直至结束。
HDFS写:客户端向namenode发一个创建文件请求->namenode创建一个新文件->namenode分配N个datanode->客户端向第一个datanode写入数据->数据复制到其它datanode。
6.HDFS文件系统相当于一个跨机器的文件管理机制,只负责将一个文件如何存放到各个节点,并统一管理。各节点上的文件系统还是传统的文件系统,例如FAT\EXT3等,但对用户来说是透明的(HDFS是一种文件管理体系,通过namenode和datanode及内部机制来实现文件管理,具体数据存储实际上还是依从各节点上的文件系统规则)
3.HDFS可靠性:
1.冗余备份:所有数据块有备份,各datanode启动的时候会生成本地文件与数据块对应关系列表,发送给namenode,即块报告。
2.副本存放:副本存放策略,本机架存放且在其它机架存放,防止机架失效数据丢失。
3.心跳检测:与各datanode通信获得运行状态及资源情况
4.安全模式:系统启动后namenode收集datanode的块报告并检查,当所有数据块副本达到最小副本数,则一段时间后推出安全模式。安全模式下不能执行写操作。
5.完整性检查:客户端校验和文件与客户端读取文件后计算结果校验。
6.空间回收:不物理删除,保存一段时间。
7.元数据备份:namenode元数据文件备份恢复,第一种方法是在配置文件中配置多个目录来存放元数据,另外一种是通过secondary namenode来存放元数据,当主机fail就可以使用这些备份恢复。
8.快照回滚:
4.HDFS场景:
1.启动:namenode启动进入安全模式-》datanode启动-》datanode块报告-》namenode检查最小备份数-》namenode退出安全模式
2.读取:客户端访问namenode获取数据块对应的datanode列表->客户端依次读取各datanode上的数据-》校验和检查
3.写入:客户端向namenode发一个创建文件请求->namenode管理目录结构创建文件记录->HDFS文件系统创一个文件->namenode划分block客户端获得计算所得的datanode列表形成pipeline->客户端向指定的第一个datanode写入数据->数据沿pipeline传给其他datanode->最后一个datanode写入完成沿pipeline反馈ack->namenode关闭
4.删除:客户端向namenode发一个删除文件请求->namenode元数据移入/trash->一定时间后不恢复则删除(datanode上的文件未被删除前)
5.NameNode元数据相关文件目录解析
格式化完成之后,将会在$dfs.namenode.name.dir/current目录下如下的文件结构
current/
|-- VERSION
|-- edits_*
|-- fsimage_0000000000008547077
|-- fsimage_0000000000008547077.md5
`-- seen_txid
其中的dfs.namenode.name.dir是在hdfs-site.xml文件中配置的,默认值如下:
file ://${hadoop.tmp.dir}/dfs/name
而hadoop.tmp.dir是在core-site.xml中配置的,默认值如下:
/tmp/hadoop-${user.name}
请留意:dfs.namenode.name.dir属性可以配置多个目录,如/data1/dfs/name,/data2/dfs/name, /data3/dfs/name,….。各个目录存储的文件结构和内容都完全一样,相当于备份,这样做的好处是当其中一个目录损坏了,也不会影响到 Hadoop的元数据,特别是当其中一个目录是NFS(网络文件系统Network File System,NFS)之上,即使你这台机器损坏了,元数据也得到保存。
下面对$dfs.namenode.name.dir/current/目录下的文件进行解释。
1、VERSION文件是Java属性文件,内容大致如下:
|
#Fri Nov 15 19:47:46 CST 2013 namespaceID=934548976 clusterID=CID-cdff7d73-93cd-4783-9399-0a22e6dce196 cTime=0 storageType=NAME_NODE blockpoolID=BP-893790215-192.168.24.72-1383809616115 layoutVersion=-47 |
其中
(1)、namespaceID是文件系统的唯一标识符,在文件系统首次格式化之后生成的;
(2)、storageType说明这个文件存储的是什么进程的数据结构信息(如果是DataNode,storageType=DATA_NODE);
(3)、cTime表示NameNode存储时间的创建时间,由于我的NameNode没有更新过,所以这里的记录值为0,以后对NameNode升级之后,cTime将会记录更新时间戳;
(4)、layoutVersion表示HDFS永久性数据结构的版本信息, 只要数据结构变更,版本号也要递减,此时的HDFS也需要升级,否则磁盘仍旧是使用旧版本的数据结构,这会导致新版本的NameNode无法使用;
(5)、clusterID是系统生成或手动指定的集群ID,在-clusterid选项中可以使用它;如下说明
a、使用如下命令格式化一个Namenode:
$ $HADOOP_HOME/bin/hdfs namenode -format [-clusterId ]
请注意:选择一个唯一的cluster_id,并且这个cluster_id不能与环境中其他集群有冲突。如果没有提供cluster_id,则会自动生成一个唯一的ClusterID。
b、使用如下命令格式化其他Namenode:
$ $HADOOP_HOME/bin/hdfs namenode -format -clusterId
c、升级集群至最新版本。在升级过程中需要提供一个ClusterID,例如:
$ $HADOOP_PREFIX_HOME/bin/hdfs start namenode
--config $HADOOP_CONF_DIR -upgrade -clusterId
如果没有提供ClusterID,则会自动生成一个ClusterID。
(6)、blockpoolID:是针对每一个Namespace所对应的blockpool的ID,上面的这个BP- 893790215-192.168.24.72-1383809616115就是在我的ns1的namespace下的存储块池的ID,这个ID包括了 其对应的NameNode节点的ip地址。
2、请注意:$dfs.namenode.name.dir/current/seen_txid非常重要,是存放transactionId的文件,format之后是0,它代表的是namenode里面的edits_*文件的尾数,namenode重启的时候,会按照seen_txid的数字, 循序从头跑edits_0000001~到seen_txid的数字。所以当你的hdfs发生异常重启的时候,一定要比对seen_txid内的数字是不 是你edits最后的尾数,不然会发生建置namenode时metaData的资料有缺少,导致误删Datanode上多余Block的资讯。
3、$dfs.namenode.name.dir/current目录下在format的同时也会生成fsimage和edits*文件,及其对应的md5校验文件。fsimage和edits是Hadoop元数据相关的重要文件,待补充。
6.DataNode相关文件目录解析
待补充