zoukankan      html  css  js  c++  java
  • Hadoop 中疑问解析

    Hadoop 中疑问解析

    FAQ问题剖析

    一、HDFS 文件备份与数据安全性分析1 HDFS 原理分析1.1 Hdfs master/slave模型

    hdfs采用的是master/slave模型,一个hdfs cluster包含一个NameNode和一些列的DataNode,其中NameNode充当的是master的角色,主要负责管理hdfs文件系统,接受来自客户端的请求;DataNode主要是用来存储数据文件,hdfs将一个文件分割成一个或多个的block,这些block可能存储在一个DataNode上或者是多个DataNode.

    具体实现如下:

    1. NameNode:基本上等同于Master的地位,复制控制底层文件的io操作,处理mapreduce任务等。

    2. DataNodeslave机器上运行,负责实际的底层的文件的读写。如果客户端client程序发起了读hdfs上的文件的命令的话,那么首先将这些文件分成所谓的block,然后NameNode将告知client这些block数据是存储在那些DataNode上的,之后,client将直接和DataNode交互。

    3. Secondary NameNode:该部分主要是定时对NameNode进行数据snapshots进行备份,这样尽量降低NameNode崩溃之后,导致数据的丢失。

    4. JobTracker:该部分相当于在client programhadoop之间的桥梁,在整个的hadoop系统中仅仅存在一个JobTracker的实例。

    5. TaskTrackerTaskTracker主要是负责的是每个具体的任务task,如下:

    1.2 文件系统命名空间File System Namespace

    hdfs支持传统文件系统的目录结构,应用程序能够创建目录directory,在这些目录中存储文件,创建文件,移动文件remove file,重命名文件,但是不支持硬链接和软连接。

    1.3 数据复制Data Replication

    hdfs将一个文件分割成block,然后将这些block存储到不同的DataNode中,那么如何保证如果一个DataNode死掉,保证数据的完整性,通常的技就是进行数据的备份,hdfs同样使用的是这一策略。

    系统启动时,NameNode首先进入SafeMode,在这种模式下是不进行数据的备份(拷贝的)的,DataNodeNameNode发送HeartbeatBlockreport,从而使得NameNode得到在每个DataNode上存储的数据文件,然后NameNode检查那些block的备份镜像数量还未达到所需备份数量,那么NameNode将对这些blocks进行备份。

    1.4 元数据持久化

    hdfs使用日志机制将对文件系统的操作全部存储在一个日志文件中,同时将整个文件系统信息(the mapping of blocks to files and file system properties)映射成一个FsImage文件,该文件存储在NameNode主机的本地文件系统上。同时FsImageLog支持multiple copies,这些hdfs保证这些备份文件的一致性。

    1.5 信息交换协议

    上面讲到“DataNodeNameNode发送HeartbeatBlockreport”,这其中显然涉及到协议的问题,hdfs communication协议是构建在tcp/ip协议上的。客户端通过ClientProtocol协议和NameNode交换信息,NameNode通过DataNode Procotol协议和DataNode交换信息。

    2 NameNode启动过程详细剖析2.1NameNode关键的数据结构2.1.1 FSImage

    Namenode会将HDFS的文件和目录元数据存储在一个叫fsimage的二进制文件中,每次保存fsimage之后到下次保存之间的所有hdfs操作,将会记录在editlog文件中,当editlog达到一定的大小(bytes,由fs.checkpoint.sizecore-site.xml设置】参数定义)或从上次保存过后一定时间段过后(sec,由fs.checkpoint.period参数定义),namenode会重新将内存中对整个HDFS的目录树和文件元数据刷到fsimage文件中。Namenode就是通过这种方式来保证HDFS中元数据信息的安全性。

    Fsimage是一个二进制文件,当中记录了HDFS中所有文件和目录的元数据信息,在我的HadoopHDFS版中,该文件的中保存文件和目录的格式如下:

    namenode重启加载fsimage时,就是按照如下格式协议从文件流中加载元数据信息。从fsimag的存储格式可以看出,fsimage保存有如下信息:

    1. 首先是一个image head,其中包含:

    a) imgVersion(int):当前image的版本信息

    b) namespaceID(int):用来确保别的HDFS instance中的datanode不会误连上当前NN

    c) numFiles(long):整个文件系统中包含有多少文件和目录

    d) genStamp(long):生成该image时的时间戳信息。

    2. 接下来便是对每个文件或目录的源数据信息,如果是目录,则包含以下信息:

    a) path(String):该目录的路径,如”/user/build/build-index”

    b) replications(short):副本数(目录虽然没有副本,但这里记录的目录副本数也为3

    c) mtime(long):该目录的修改时间的时间戳信息

    d) atime(long):该目录的访问时间的时间戳信息

    e) blocksize(long):目录的blocksize都为0

    f) numBlocks(int):实际有多少个文件块,目录的该值都为-1,表示该item为目录

    g) nsQuota(long)namespace Quota值,若没加Quota限制则为-1

    h) dsQuota(long)disk Quota值,若没加限制则也为-1

    i) username(String):该目录的所属用户名

    j) group(String):该目录的所属组

    k) permission(short):该目录的permission信息,如644等,有一个short来记录。

    3. 若从fsimage中读到的item是一个文件,则还会额外包含如下信息:

    a) blockid(long):属于该文件的blockblockid

    b) numBytes(long):该block的大小

    c) genStamp(long):该block的时间戳

    当该文件对应的numBlocks数不为1,而是大于1时,表示该文件对应有多个block信息,此时紧接在该fsimage之后的就会有多个blockidnumBytesgenStamp信息。

    因此,在namenode启动时,就需要对fsimage按照如下格式进行顺序的加载,以将fsimage中记录的HDFS元数据信息加载到内存中。

    2.2.2 BlockMap

    从以上fsimage中加载如namenode内存中的信息中可以很明显的看出,在fsimage中,并没有记录每一个block对应到哪几个datanodes的对应表信息,而只是存储了所有的关于namespace的相关信息。而真正每个block对应到datanodes列表的信息在hadoop中并没有进行持久化存储,而是在所有datanode启动时,每个datanode对本地磁盘进行扫描,将本datanode上保存的block信息汇报给namenodenamenode在接收到每个datanode的块信息汇报后,将接收到的块信息,以及其所在的datanode信息等保存在内存中。HDFS就是通过这种块信息汇报的方式来完成block -> datanodes list的对应表构建。Datanodenamenode汇报块信息的过程叫做blockReport,而namenodeblock -> datanodes list的对应表信息保存在一个叫BlocksMap的数据结构中。

    BlocksMap的内部数据结构如下:   

    如上图显示,BlocksMap实际上就是一个Block对象对BlockInfo对象的一个Map表,其中Block对象中只记录了blockidblock大小以及时间戳信息,这些信息在fsimage中都有记录。而BlockInfo是从Block对象继承而来,因此除了Block对象中保存的信息外,还包括代表该block所属的HDFS文件的INodeFile对象引用以及该block所属datanodes列表的信息(即上图中的DN1DN2DN3,该数据结构会在下文详述)。

    因此在namenode启动并加载fsimage完成之后,实际上BlocksMap中的key,也就是Block对象都已经加载到BlocksMap中,每个key对应的value(BlockInfo)中,除了表示其所属的datanodes列表的数组为空外,其他信息也都已经成功加载。所以可以说:fsimage加载完毕后,BlocksMap中仅缺少每个块对应到其所属的datanodes list的对应关系信息。所缺这些信息,就是通过上文提到的从各datanode接收blockReport来构建。当所有的datanode汇报给namenodeblockReport处理完毕后,BlocksMap整个结构也就构建完成。

    BlockMapdatanode列表数据结构

    BlockInfo中,将该block所属的datanodes列表保存在一个Object[]数组中,但该数组不仅仅保存了datanodes列表,还包含了额外的信息。实际上该数组保存了如下信息:

    上图表示一个block包含有三个副本,分别放置在DN1DN2DN3三个datanode上,每个datanode对应一个三元组,该三元组中的第二个元素,即上图中prev block所指的是该block在该datanode上的前一个BlockInfo引用。第三个元素,也就是上图中next Block所指的是该block在该datanode上的下一个BlockInfo引用。每个block有多少个副本,其对应的BlockInfo对象中就会有多少个这种三元组。

           Namenode采用这种结构来保存block->datanode list的目的在于节约namenode内存。由于namenodeblock->datanodes的对应关系保存在了内存当中,随着HDFS中文件数的增加,block数也会相应的增加,namenode为了保存block->datanodes的信息已经耗费了相当多的内存,如果还像这种方式一样的保存datanode->block list的对应表,势必耗费更多的内存,而且在实际应用中,要查一个datanode上保存的block list的应用实际上非常的少,大部分情况下是要根据block来查datanode列表,所以namenode中通过上图的方式来保存block->datanode list的对应关系,当需要查询datanode->block list的对应关系时,只需要沿着该数据结构中next Block的指向关系,就能得出结果,而又无需保存datanode->block list在内存中。

    3副本放置策略

    第一个block副本放在和client所在的node里(如果client不在集群范围内,则这第一个node是随机选取的,当然系统会尝试不选择哪些太满或者太忙的node)。

    第二个副本放置在与第一个节点不同的机架中的node中(随机选择)。

    第三个副本和第二个在同一个机架,随机放在不同的node中。

    如果还有更多的副本就随机放在集群的node里。

    Hadoop的副本放置策略在可靠性(block在不同的机架)和带宽(一个管道只需要穿越一个网络节点)中做了一个很好的平衡。下图是备份参数是3的情况下一个管道的三个datanode的分布情况。

    二、误删文件恢复方案

    利用hadoop fs -rmr (目录名)删除目录时易出现误删除的操作,如何解决:建立回收站

    具体操作为:

    找到配置文件core-site.xml,在其中添加如下信息:

    <property> <name>fs.trash.interval</name> <value>10080</value> <description> Number of minutes between trash checkpoints. If zero, the trash feature is disabled. </description> </property>

    其中10080代表分钟数,即代表删除的文件或目录在".Trash"(回收站)中保留的时间,可自行设置。保存即可。

    hadoop fs -lsr 时暂时看不到.Trash,再删除某个文件或者目录之后,再次用lsr即可看到所在目录下的回收站.Trash已经建好:

    再用hadoop fs -mv /user/cloud/.Trash/Current/user/cloud/123456789 /user/cloud ,即可把误删除的123456789目录恢复。

    Hadoop冗余机制实验验证

    Hadoop冗余机制实验验证3.1副本系数为1的验证

    设置副本系数为1,也就是说存放在HDFS 中的文件每个块值存储一次,当块损坏时将

    无法正常读取数据。

    使用Hadoop org.apache.hadoop.examples.terasort 下的TeraGen 类来生成10000000

    1GB记录数据,命令如下:

    hadoop jar hadoop/hadoop-*-examples.jar teragen 10000000 terasort/input-GB001

    生成后进行排序的命令为:

    bin/hadoop jar hadoop-0.20.2-examples.jar terasort

    terasort/input-GB001 terasort/output-GB001

    正常情况下:

    运行完的截图如下:

    通过WEB接口可以看到运行时并无失效节点和异常,截图如下:

    节点失效情况下

    然后认为的将一个节点关机,发现出现两个读取错误,如下图:

    通过WEB接口也可以发现有两个警告和一个死亡节点,截图如下:

    通过这个实验,我们发现当设置副本系数为1 是,Hadoop 集群的数据没有进行冗余备

    份,当出现某个节点失效时,便会出现异常,致使提交的作业无法正常完成。

    3.2副本系数为3的验证

    设置副本系数为3,也就是每个文件的分块块都有三个复制备份,当某些数据块出错时,

    HDFS 可以通过复制完整的副本来产生一个新的,来治愈那些出错的数据块,使得数据块的

    副本恢复到预期设定的数量来保证数据的高可靠性,一个因损坏或者机器故障而丢失的块会

    从其他候选地点来复制来正常运行的机器上。

    同样产生排序所需数据然后运行排序作业,然后我们通过WEB 接口也可以发现文件的

    属性

    可以看到复制因子为3,块的大小为64M

    运行时人为的关闭一个机器,仍然正常运行,并成功完成排序任务:

    总结

    通过实验验,我们验证了Hadoop 的冗余复制机制,这种机制保证了存放在HDFS 中的数据的高可靠性和数据的完整一致性。

  • 相关阅读:
    June. 26th 2018, Week 26th. Tuesday
    June. 25th 2018, Week 26th. Monday
    June. 24th 2018, Week 26th. Sunday
    June. 23rd 2018, Week 25th. Saturday
    June. 22 2018, Week 25th. Friday
    June. 21 2018, Week 25th. Thursday
    June. 20 2018, Week 25th. Wednesday
    【2018.10.11 C与C++基础】C Preprocessor的功能及缺陷(草稿)
    June.19 2018, Week 25th Tuesday
    June 18. 2018, Week 25th. Monday
  • 原文地址:https://www.cnblogs.com/elwiny/p/hadoop_FAQ.html
Copyright © 2011-2022 走看看