一.HDFS简介
1.HDFS简介
HDFS是hadoop的核心子项目,是一个可以运行在普通硬件设备上的分布式文件系统,也就是容错很高;是基于流数据模式访问和处理超大文件的需求开发的,它具有高容错,高可靠性,高可拓展性,高吞吐率等特点。
2.HDFS的架构和数据存储原理
上面这张图就是HDFS的架构图,这种架构主要由四个部分组成,HDFS Client,NameNode,Secondary NameNode,DataNode. Client通过NameNode获取文件的元数据,而真正的文件I/O操作则是直接和DataNode交互的。
下面分别介绍一下四个角色的分工:
Clinet:
1.文件切分。文件上传的时候,是Client自动将文件切分成一个一个的Block,然后进行存储
2.与NameNode交互,获取文件位置信息,与DataNode交互,读写数据
3.管理访问HDFS,比如启动或者关闭HDFS,查看一些配置信息,文件路径等等
NameNode:
1.管理HDFS的名称空间
2.管理数据块的映射信息 (一个Block块是128M,和普通的文件系统不一样的是,如果这个Block没满他就不占用128M,有多大就占多大的空间,不会浪费)
3.配置副本策略 (就是你上传的文件给你保存几份的意思)
Namenode中的数据书存储在内存中的,内存中的数据断电就没了,如何持久化存储呢?
使用SecondaryNameNode来辅助元数据的持久化存储,因为平时都是一个NameNode在Active,所以一般不会在NameNode上进行元数据的持久化存储。而是通过SecondaryNameNode定时将数据从NameNode上拉下来,根据editlog生成新的fsimage然后更新到NameNode上。
如何解决editlog过大的问题?
DataNode:
1.存储实际的数据块,执行数据块的读写操作
Secondary NameNode:
并非是NameNode的热备,而是冷备。当NameNode挂掉的时候,它并不能马上替换NameNode并提供服务。
1.辅助NameNode,分担其工作量
2.定期合并fsimage和fsedits,并推送给NameNode(fsimage:元数据镜像文件,文件系统的目录树,比如有哪些目录,目录下面都有什么文件 fsedits:元数据操作日志 针对目录树的修改操作,比如你增加删除可某些文件目录之类的,都会给你记录到这个文件下面)
3.在紧急情况下,可辅助恢复NameNode
首先NameNode会生成一个新的edit文件,然后SecondaryNamenode会把NameNode上面的edit和fsImage文件复制过来,生成一个新的fsimage。ckpt文件,然后替换NameNode中的fsimage。
可以通过配置文件设置这个checkpoint的时间:
3.HDFS副本的存放策略
4.机架感知
机架感知是什么?
告诉Hadoop集群中哪台机器属于哪个机架。Hadoop 对机架的感知并非是自适应的,亦即,hadoop 集群分辨某台 slave 机器是属于哪个 rack 并非智能感知的,而是需要 hadoop的管理者人为的告知 hadoop 哪台机器属于哪个 rack,这样在 hadoop的 namenode 启动初始化时,会将这些机器rack 的对应信息保存在内存中,用来作为对接下来所有的 HDFS 的写块操作分配 datanode列表时(比如 3 个 block 对应三台 datanode)的选择 datanode策略,尽量将三个副本分布到不同的 rack。
怎么告诉hadoop集群中哪台机器属于哪个机架?
通过什么方式能够告知hadoop namenode哪些slave机器属于哪个rack?
要将 hadoop 机架感知的功能启用,配置非常简单,在 namenode
所在机器的 hadoop-site.xml 配置文件中配置一个选项:
topology.script.file.name
/path/to/RackAware.py
这个配置选项的 value 指定为一个可执行程序,通常为一个脚本,该脚本接受一个参数,输出一个值。接受的参数通常为某台 datanode机器的 ip 地址,而输出的值通常为该 ip 地址对应的 datanode 所在的 rack,例如”/rack1”。Namenode 启动时,会判断该配置选项是否为空,如果非空,则表示已经用机架感知的配置,此时 namenode会根据配置寻找该脚本,并在接收到每一个 datanode 的 heartbeat时,将该 datanode 的 ip 地址作为参数传给该脚本运行,并将得到的输出作为该 datanode 所属的机架,保存到内存的一个 map 中。至于脚本的编写,就需要将真实的网络拓朴和机架信息了解清楚后,通过该脚本能够将机器的 ip 地址正确的映射到相应的机架上去。
一个简单的实现如下:
#!/usr/bin/python
#-*-coding:UTF-8 -*-
import sys
rack = {"hadoopnode-176.tj":"rack1",
"hadoopnode-178.tj":"rack1",
"hadoopnode-179.tj":"rack1",
"hadoopnode-180.tj":"rack1",
"hadoopnode-186.tj":"rack2",
"hadoopnode-187.tj":"rack2",
"hadoopnode-188.tj":"rack2",
"hadoopnode-190.tj":"rack2",
"192.168.1.15":"rack1",
"192.168.1.17":"rack1",
"192.168.1.18":"rack1",
"192.168.1.19":"rack1",
"192.168.1.25":"rack2",
"192.168.1.26":"rack2",
"192.168.1.27":"rack2",
"192.168.1.29":"rack2",
}
if __name__=="__main__":
print "/" + rack.get(sys.argv[1],"rack0")
重启 namenode,如果配置成功,namenode 启动日志中会输出:
INFO [org.apache.hadoop.net.NetworkTopology](http://org.apache.hadoop.net.networktopology/): Adding a
new node: /rack1/192.168.1.15:50010
三.HDFS2的新特性HA和Federation
1.HDFS的HA机制
hadoop2.2.0之前,NameNode存在单点故障,每个集群只有一个NameNode。如果这个机器宕机将导致集群不可用。HA通过提供选择运行再同一集群中的一个热备用的“主/备”两个冗余NameNode,就可以再机器宕机或系统维护的时候快速转移到另一个NameNode.
1.为了保持备用节点与活动节点状态的同步,目前的实现是两个节点同时访问一个共享存储设备(例如从NASNFS挂载)到一个目录。
2.活动节点对命名空间的任何修改都会记录到共享目录下的一个日志文件,备用节点就会监听这个目录,当发现更改试就会同步到自己的命名空间。备用节点再故障转移试,它将保证已经读取了所有共享目录内的更改记录,保证在发生故障前的状态与活动节点保持一致。
3.为了提供快速的故障转移,必须保证备用节点有最新的集群中块的位置信息,为了达到这一点,DataNode节点配置两个nameNode的位置,同时发送块的位置信息和心跳信息到两个NameNode
4.任何时候只有一个NameNode处于活动状态,否则两个节点之间的状态就会产生冲突,数据丢失或其他不正确的结果,为了达到这个目的或者所谓的“裂脑场景”出现,管理员必须为共享存储配置至少一个(fencing)方法。在宕机期间,如果不能确定之间的活动节点已经放弃活动状态,fencing进程负责中断以前的活动节点编辑存储的共享访问,这可以防止任何进一步的修改命名空间,允许新的活动节点安全的进行故障转移。
2.NameNode的Federation
四.HDFS的读写流程
1.HDFS的写文件流程
首先HDFS客户端会在本地创建一个临时文件,当临时文件达到一个块的大小的时候通知NameNode(如果是小文件的话,不到一个数据块,写完后也会直接通知NameNode的),NameNode会返回给客户端要写入的DataNode的地址,然后客户端直接写到对应的DataNode就好了。如果是设置了三个副本的话,那么在客户端写数据到三个DataNode的时候就是这样来写:首先会把数据packet(一个packet4kb)写到最近的DataNode,写完之后这个DataNode会把这个packet传到下一个DataNode去写,等到写完最后一个DataNode的时候,最后的DataNode会把写数据的结果返回给上一个DataNode,依次上传,这样形成一个管道,等到文件都写完成之后,再次通知到NameNode。
上面这是正常情况下的写数据流程,那么当写数据的过程中出了点幺蛾子呢?比如在DataNode管道之间传数据的时候,比如第二个DataNode节点写着写着挂掉了,这个时候会发生什么呢?这个时候第一个DataNode会直接向第三个DataNode去写数据,当两个DataNode写完之后,在给NameNode通知块报告的时候,NameNode会发现少了一个副本,这时候NameNode就会在选择一个新的DataNode去写第三个副本。最后当原来已经传输了一半挂掉的DataNode启动起来之后,NameNode会通知它删除掉原来传了一半的文件。
2.HDFS的读数据流程
读数据流程就很简单了,就是客户端连接NameNode,然后NameNode告诉客户端你要读的数据在哪台DataNode上面,然后就可以通过API读了。
五.HDFS数据的完整性
为了保证数据的完整性,一般採用数据校验技术: 奇偶校验技术 、md5,sha1等校验技术 、CRC-32循环冗余校验技术 、ECC内存纠错校验技术
1、HDFS以透明方式校验全部写入的数据。能够通过io.bytes.per.checksum属性设置,字节数默认是512 字节。创建一个单独的校验和。假设节点检測数据错误。就会报CheckSumException异常。
2、除了在读取数据时进行验证,数据节点也会在后台执行一个线程
DataBlockscanner(数据块检測程序)周期性的验证存储在数据节点上的全部块。
3、一旦检測到corruptblock,在heartbeat阶段,DN会收到NN发来的Block Command。从其它数据块中拷贝一份新的replica(备份块)
六.安全模式
什么是安全模式
安全模式是HDFS所处的一种特殊状态,在这种状态下,文件系统只接受读数据请求,而不接受删除、修改等变更请求。在NameNode主节点启动时,HDFS首先进入安全模式,DataNode在启动的时候会向namenode汇报可用的block等状态,当整个系统达到安全标准时,HDFS自动离开安全模式。如果HDFS出于安全模式下,则文件block不能进行任何的副本复制操作,因此达到最小的副本数量要求是基于datanode启动时的状态来判定的,启动时不会再做任何复制(从而达到最小副本数量要求)
下面是namenode的一个日志片段:
安全模式相关的配置
系统什么时候才离开安全模式,需要满足哪些条件?当收到来自datanode的状态报告后,namenode根据配置,确定 1)可用的block占总数的比例、2)可用的数据节点数量符合要求之后,离开安全模式。如果有必要,也可以通过命令强制离开安全模式。与安全模式相关的主要配置在hdfs-site.xml文件中,主要有下面几个属性
dfs.namenode.replication.min: 最小的文件block副本数量,默认为1.
dfs.namenode.safemode.threshold-pct: 副本数达到最小要求的block占系统总block数的百分比,当实际比例超过该配置后,才能离开安全模式(但是还需要其他条件也满足)。默认为0.999f,也就是说符合最小副本数要求的block占比超过99.9%时,并且其他条件也满足才能离开安全模式。如果为小于等于0,则不会等待任何副本达到要求即可离开。如果大于1,则永远处于安全模式。
dfs.namenode.safemode.min.datanodes: 离开安全模式的最小可用(alive)datanode数量要求,默认为0.也就是即使所有datanode都不可用,仍然可以离开安全模式。
dfs.namenode.safemode.extension: 当集群可用block比例,可用datanode都达到要求之后,如果在extension配置的时间段之后依然能满足要求,此时集群才离开安全模式。单位为毫秒,默认为1.也就是当满足条件并且能够维持1毫秒之后,离开安全模式。 这个配置主要是对集群的稳定程度做进一步的确认。避免达到要求后马上又不符合安全标准。
总结一下,要离开安全模式,需要满足以下条件:
1)达到副本数量要求的block比例满足要求;
2)可用的datanode节点数满足配置的数量要求;
3) 1、2 两个条件满足后维持的时间达到配置的要求。
我们可以再次从日志中验证这些:
相关的操作命令
Hadoop提供脚本用于对安全模式进行操作,主要命令为:
·hadoop dfsadmin -safemode
command的可用取值如下: