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

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

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

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

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

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

1.3 数据复制Data Replication

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

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

1.4 元数据持久化

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

1.5 信息交换协议

上面讲到“DataNode向NameNode发送Heartbeat和Blockreport”,这其中显然涉及到协议的问题,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.size【core-site.xml设置】参数定义)或从上次保存过后一定时间段过后(sec,由fs.checkpoint.period参数定义),namenode会重新将内存中对整个HDFS的目录树和文件元数据刷到fsimage文件中。Namenode就是通过这种方式来保证HDFS中元数据信息的安全性。

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

当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):属于该文件的block的blockid,

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

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

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

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

2.2.2 BlockMap

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

BlocksMap的内部数据结构如下:

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

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

BlockMapdatanode列表数据结构

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

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

Namenode采用这种结构来保存block->datanode list的目的在于节约namenode内存。由于namenode将block->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里。

的情况下一个管道的三个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 中的数据的高可靠性和数据的完整一致性。

Hadoop 中疑问解析的更多相关文章

  1. Hadoop中Partition解析

    1.解析Partition Map的结果,会通过partition分发到Reducer上,Reducer做完Reduce操作后,通过OutputFormat,进行输出,下面我们就来分析参与这个过程的类 ...

  2. Hadoop中OutputFormat解析

    一.OutputFormat OutputFormat描述的是MapReduce的输出格式,它主要的任务是: 1.验证job输出格式的有效性,如:检查输出的目录是否存在. 2.通过实现RecordWr ...

  3. Hadoop中Yarnrunner里面submit Job以及AM生成 至Job处理过程源码解析

    参考 http://blog.csdn.net/caodaoxi/article/details/12970993 Hadoop中Yarnrunner里面submit Job以及AM生成 至Job处理 ...

  4. 用shell获得hadoop中mapreduce任务运行结果的状态

    在近期的工作中,我需要用脚本来运行mapreduce,并且要判断运行的结果,根据结果来做下一步的动作. 开始我想到shell中获得上一条命令运行结果的方法,即判断"$?"的值 if ...

  5. hadoop中实现java网络爬虫

    这一篇网络爬虫的实现就要联系上大数据了.在前两篇java实现网络爬虫和heritrix实现网络爬虫的基础上,这一次是要完整的做一次数据的收集.数据上传.数据分析.数据结果读取.数据可视化. 需要用到 ...

  6. hadoop中OutputFormat 接口的设计与实现

    OutputFormat 主要用于描述输出数据的格式,它能够将用户提供的 key/value 对写入特定格式的文件中. 本文将介绍 Hadoop 如何设计 OutputFormat 接口 , 以及一些 ...

  7. hadoop中InputFormat 接口的设计与实现

    InputFormat 主要用于描述输入数据的格式, 它提供以下两个功能.❑数据切分:按照某个策略将输入数据切分成若干个 split, 以便确定 Map Task 个数以及对应的 split.❑为 M ...

  8. (转)超详细单机版搭建hadoop环境图文解析

                        超详细单机版搭建hadoop环境图文解析   安装过程: 一.安装Linux操作系统 二.在Ubuntu下创建hadoop用户组和用户 三.在Ubuntu下安装 ...

  9. Hadoop中的排序和连接

    MapReduce的全排序 主要是为了保证分区排序,即第一个分区的最后一个Key值小于第二个分区的第一个Key值 与普通的排序仅仅多一个自定义分区类MyPartitioner见自己所写的实验 (设置一 ...

随机推荐

  1. Regex count lowercase letters

    Description: Your task is simply to count the total number of lowercase letters in a string. Example ...

  2. STL笔记(6)标准库:标准库中的排序算法

    STL笔记(6)标准库:标准库中的排序算法 标准库:标准库中的排序算法The Standard Librarian: Sorting in the Standard Library Matthew A ...

  3. JSON 之 SuperObject(9): TSuperType

    unit Unit1; interface uses   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, For ...

  4. java线程安全理解

    java线程安全理解 如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码.如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的. ...

  5. CSS之可收缩的底部边框

    简述 <div>用来定义文档中的分区或节,<span>用来组合文档中的行内元素.我们可以通过<div>和 <span>将HTML元素组合起来. 下面我们 ...

  6. tarjan总结

    先说一下割点跟割边吧. 割桥就是如果一个连通图里删除这条边之后,这个图会变成两个连通图,那么这条边就称之为割桥. 这是割桥的代码,里面呆着lca求法. 割点和割桥的就是用一个时间戳和回到祖先确定. 用 ...

  7. 【第二篇】.NET用NPOI读取Excel表格并在页面预览

    博主用的是npoi2.0.1,支持.xls也支持.xlsx 直接上代码吧. <table class="table table-bordered table-striped" ...

  8. ubuntu16.04 64位server安装php7

    You can do the following: sudo apt-get install python-software-properties sudo LC_ALL=C.UTF-8 add-ap ...

  9. MySQL内存表-临时表

    HEAP表是访问数据速度最快的MySQL表,他使用保存在内存中的散列索引.但如果MySQL或者服务器重新启动,表中数据将会丢失.用法:如论坛的在线人数统计,这种表的数据应该是无关紧要的,就几个简单的字 ...

  10. Linux多线程下载工具Axel

    一般情况,在 Linux 下我们习惯于用 wget 下载,但该工具的缺点就是无法进行多线程下载,所以往往有时候速度不够快.这里介绍的 Axel,是 Linux 下一款不错的 HTTP 或 FTP 高速 ...