欢迎投稿

今日深度:

《Hadoop权威指南》——3、Hadoop 分布式文件系统,

《Hadoop权威指南》——3、Hadoop 分布式文件系统,


转载自:http://blog.csdn.net/weixuehao/article/details/16967485

大部分内容转载自以上博客,对某些地方进行了适当的补充。


简介

HDFS(Hadoop Distributed File System )Hadoop分布式文件系统。是根据google发表的论文翻版的。论文为GFS(Google File System)Google 文件系统(中文,英文)。

HDFS的设计

      以流式数据访问模式来存储超大文件。

      2.构建思路:一次写入多次读取是最高效的访问模式。

      3.HDFS是为高数据吞吐量优化的,代价是高时间延迟。对于低延迟访问需求HBase更合适。

      4.由于nameNode 将文件系统元数据存储在内存中,因此该文件系统所能存储的文件总数受限于nameNode的内存容量。

      5.不支持多写入者,也不支持任意位置的修改。

HDFS有很多特点

    ① 保存多个副本,且提供容错机制,副本丢失或宕机自动恢复。默认存3份。

    ② 运行在廉价的机器上。

    ③ 适合大数据的处理。多大?多小?HDFS默认会将文件分割成block,64M为1个block,但更多的是用的128M,块如此大是为了减少寻址开销。然后将block按键值对存储在HDFS上,并将键值对的映射存到内存中。如果小文件太多,那内存的负担会很重。

如上图所示,HDFS也是按照Master和Slave的结构。分NameNode、SecondaryNameNode、DataNode这几个角色。

NameNode:是Master节点,是大领导。管理数据块映射;处理客户端的读写请求;配置副本策略;管理HDFS的名称空间;

                     管理文件系统命名空间,维护着文件系统树及整棵树内所以文件和目录。

     这些信息以两个文件形式永久保存在本地磁盘:命名空间镜像文件编辑日志文件。mameNode 也记录着每个文件中各个块所在的节点信息。但并不永久保存块的位置信息。这些信息会在系统启动时由数据节点重建。

SecondaryNameNode:是一个小弟,分担大哥namenode的工作量;是NameNode的冷备份;合并fsimage和fsedits然后再发给namenode。

DataNode:Slave节点,奴隶,干活的。负责存储client发来的数据块block;执行数据块的读写操作。

存储并检索数据块,定期向nameNode发送他所存储块的列表。

热备份:b是a的热备份,如果a坏掉。那么b马上运行代替a的工作。

冷备份:b是a的冷备份,如果a坏掉。那么b不能马上代替a工作。但是b上存储a的一些信息,减少a坏掉之后的损失。

fsimage:元数据镜像文件(文件系统的目录树。)

edits:元数据的操作日志(针对文件系统做的修改操作记录)

namenode内存中存储的是=fsimage+edits。

SecondaryNameNode负责定时默认1小时,从namenode上,获取fsimage和edits来进行合并,然后再发送给namenode。减少namenode的工作量。

nameNode实现容错非常重要,Hadoop为此提供了两种机制:


 1、备份那些组成文件系统元数据持久状态的文件。(实时同步,是原子操作。

 2、运行一个辅助nameNode,但他不能被用作nameNode.

      作用:定期通过编辑日志合并命名空间镜像,以防止编辑日志过大。(一般在另一台计算机运行,因为占用cup)

                她保存合并后的命名空间镜像的副本,并在nameNode发生故障时启用。难免会有部分数据丢失,把存储在NFS上的nameNode元数据复制到nameNode以解决数据丢失问题,并作为新的主nameNode.

联邦HDFS:允许系统通过添加nameNode实现扩展,每个nameNode维护一个命名空间卷,命名空间卷之间是相互独立的,两两之间并不相互通信。因此不会相互影响。这样dataNode需要注册到每个nameNode,存储来自多个数据块池中的数据。

HDFS高可用:54页


 

工作原理

写操作:

有一个文件FileA,100M大小。Client将FileA写入到HDFS上。

HDFS按默认配置。

HDFS分布在三个机架上Rack1,Rack2,Rack3。

 

a. Client将FileA按64M分块。分成两块,block1和Block2;

b. Client向nameNode发送写数据请求,如图蓝色虚线①------>。

c. NameNode节点,记录block信息。并返回可用的DataNode,如粉色虚线--------->

    Block1: host2,host1,host3

    Block2: host7,host8,host4

    原理:

        NameNode具有RackAware机架感知功能,这个可以配置。

        若client为DataNode节点,那存储block时,规则为:副本1,同client的节点上;副本2,不同机架节点上;副本3,同第二个副本机架的另一个节点上;其他副本随机挑选。

        若client不为DataNode节点,那存储block时,规则为:副本1,随机选择一个节点上;副本2,不同副本1,机架上;副本3,同副本2相同的另一个节点上;其他副本随机挑选。

d. client向DataNode发送block1;发送过程是以流式写入。

    流式写入过程,

        1>将64M的block1按64k的package划分;

        2>然后将第一个package发送给host2;

        3>host2接收完后,将第一个package发送给host1,同时client想host2发送第二个package;

        4>host1接收完第一个package后,发送给host3,同时接收host2发来的第二个package。

        5>以此类推,如图红线实线所示,直到将block1发送完毕。

        6>host2,host1,host3向NameNode,host2向Client发送通知,说“消息发送完了”。如图粉红颜色实线所示。

        7>client收到host2发来的消息后,向namenode发送消息,说我写完了。这样就真完成了。如图黄色粗实线

        8>发送完block1后,再向host7,host8,host4发送block2,如图蓝色实线所示。

        9>发送完block2后,host7,host8,host4向NameNode,host7向Client发送通知,如图浅绿色实线所示。

        10>client向NameNode发送消息,说我写完了,如图黄色粗实线。。。这样就完毕了。

分析,通过写过程,我们可以了解到:

    写1T文件,我们需要3T的存储,3T的网络流量贷款。

    在执行读或写的过程中,NameNode和DataNode通过HeartBeat进行保存通信,确定DataNode活着。如果发现DataNode死掉了,就将死掉的DataNode上的数据,放到其他节点去。读取时,要读其他节点去。

    挂掉一个节点,没关系,还有其他节点可以备份;甚至,挂掉某一个机架,也没关系;其他机架上,也有备份。

 

读操作:

 

读操作就简单一些了,如图所示,client要从datanode上,读取FileA。而FileA由block1和block2组成。 

 

那么,读操作流程为:

a. client向namenode发送读请求。

b. namenode查看Metadata信息,返回fileA的block的位置。

    block1:host2,host1,host3

    block2:host7,host8,host4

c. block的位置是有先后顺序的,先读block1,再读block2。而且block1去host2上读取;然后block2,去host7上读取;

 

上面例子中,client位于机架外,那么如果client位于机架内某个DataNode上,例如,client是host6。那么读取的时候,遵循的规律是:

优选读取本机架上的数据

 


HDFS中常用到的命令

1、hadoop fs

[java] view plain copy
  1. hadoop fs -ls /  
  2. hadoop fs -lsr  
  3. hadoop fs -mkdir /user/hadoop  
  4. hadoop fs -put a.txt /user/hadoop/  
  5. hadoop fs -get /user/hadoop/a.txt /  
  6. hadoop fs -cp src dst  
  7. hadoop fs -mv src dst  
  8. hadoop fs -cat /user/hadoop/a.txt  
  9. hadoop fs -rm /user/hadoop/a.txt  
  10. hadoop fs -rmr /user/hadoop/a.txt  
  11. hadoop fs -text /user/hadoop/a.txt  
  12. hadoop fs -copyFromLocal localsrc dst 与hadoop fs -put功能类似。  
  13. hadoop fs -moveFromLocal localsrc dst 将本地文件上传到hdfs,同时删除本地文件。  

2、hadoop fsadmin 

[java] view plain copy
  1. hadoop dfsadmin -report  
  2. hadoop dfsadmin -safemode enter | leave | get | wait  
  3. hadoop dfsadmin -setBalancerBandwidth 1000  

3、hadoop fsck

4、start-balancer.sh



3.2.3 命令行接口

伪分布配置.

fs.default.name, 设置为 hdfs://localhost/, 为Hadoop的默认文件系统. HDFS的daemon会通过此确定HDFS namenode的主机及端口. 默认8020.

dfs.replication, 此时设置为1, 一般为3. 因为是单机模式. 不然为警告块副本不足.

3.2.4 基础文件系统操作

帮助:

% hadoop fs -help

复制:

% hadoop fs -copyFromLocal input/docs/quangle.txt hdfs://localhost/user/tom/quangle.txt

检查复制是否成功:

% hadoop fs -copyFromLocal quangle.txt quangle.copy.txt
% md5 input/docs/quangle.txt quangle.copy.txt

创建文件夹:

% hadoop fs -mkdir books
% hadoop fs -ls .

3.2.5 Hadoop文件系统

Hadoop有一个抽象的文件系统, HDFS只是它的一种实现.

org.apache.hadoop.fs.FileSystem, 该抽象类定义了Hadoop中的一个文件系统接口. 具体实现有: local, HDFS, HFTP, HSFTP, HAR, hfs, FTP S3, S3.

3.2.6 接口

文件系统的命令行解释器就是一个java

Thrift, C语言, FUSE, WebDAV.

3.2.7 其他HDFS接口

HTTP(只读), FTP.

3.3 Java 接口

深入探索Hadoop的 Filesystem 类: 与Hadoop某一文件系统交互的API.

由于本书使用的是0.20.0版本, 并且成文方式类似于字典. 这一块的学习暂时仅浏览一遍. 不需记录.

不过, 还是记录下涉及到的类的名字.

3.3.1 从Hadoop URL中读取数据

类名/方法名 简单描述
java.net.URL 从Hadoop文件系统读取对象时, 打开数据流
URL().openStream() 方法
IOUtils.closeStream() Hadoop简洁的IOUtils类
URL.setURLStreamHandlerFactory()  
FsUrlStreamHandlerFactory()  
   

3.3.2 通过FileSystem API读取数据

类名/方法名 简单描述
static FileSystem get(Configuration conf) throws IOException 获取FileSystem实例的两种静态工厂方法
static FileSystem get(URI uri, Configuration conf) throws IOException  
Configuration 封装客户端或服务端配置
FSDataInputStream open(Path f) throws IOException 调用open()获取文件的输入流
abstract FSDataInputStream open(Path f, int bufferSize) throws IOException 调用open()获取文件的输入流
Hadoop Path 不用java.io.File对象表示文件
  1. FSDataInputStream

    FSDataInputStream对象, 而不是标准的java.io类对象.

    public class FSDataInputStream extends DataInputStream
        implements Seekable, PositionedReadable {
        // implementation elided
    }
    

    Seekable 接口支持在文件中找到任意位置.

    public interface Seekable {
        void seek(long pos) throws IOException; //定位到绝对位置, 于java.io.InputStream#skip()不同
        long getPos() throws IOException;
        boolean seekToNewSource(long targetPos) throws IOException;
    }
    

    注意seek(),高开销, 建议用流数据构建应用的访问模式, 比如使用MapReduce.

    PositionedReadable 接口, 从一个偏移量处读取文件的一部分.

    public interface Positionedable {
        // int read()
        // void readFully()
        // void readFully()
    }
    

3.3.3 写入数据

3.3.4 查询文件系统

3.3.5 删除数据

3.4 数据流

 

3.4.1 文件读取剖析

Client, HDFS, namenode 和 datanode.

客户端读取HDFS中的数据

3.4.2 文件写入分析

我们考虑的情况是, 如何创建一个新文件, 并把数据写入该文件, 最后关闭该文件.

客户端往HDFS写入数据
  1. 客户端通过 DistributedFileSystem 对象调用 create() 创建文件;
  2. DistributedFileSystem 对 namenode 创建一个 RPC 调用. 此时文件还没有相对应的数据块. namenode执行各种检查确保文件不存在, 且客户端有创建的权限. 如果通过, 创建一条新文件记录, 否则, 抛出 IOException;
  3. DistributedFileSystem 对象向客户端返回一个 FSDataOutputStream 对象, 由此, 客户端开始写入数据. 同时, FSDataOutputStream 对象封装一个 DFSoutPutstream 对象, 该对象负责处理 datanode 和 namenode 之间的通信;
  4. 客户端如何写入数据呢? FSDataOutputStream 将数据分成一个个数据包, 并写入内部队列, 称为”数据队列”(data queue). DataStreamer 处理队列, 根据 datanode 列表来要求 namenode 分配适合的新块储存数据备份. 这一组 datanode 构成一个 pipe line – 我们假设副本为3. DataStreamer 将数据包流式传输到管线中的第一个 datanode, 该 datanode 存储数据包并将它发送到管线中的第2个 datanode. 同样第2个存储并发送到第3个(最后一个).
  5. DFSOutputStream 也维护着一个内部数据包队列来等待 datanode 的收到确认回执, 称为确认队列(ack queue). 当收到所有 datanode 的确认信息, 该队列会从确认队列中删除;
  6. 完成后, 调用 close() ;
  7. 并等待 namenode 确认已经知道文件由哪些块组成(通过 DataStreamer 询问数据块的分配);

3.5 一致模型

文件系统的 一致模型 (coherency model) 描述了对文件读/写的数据可见性.


www.htsjk.Com true http://www.htsjk.com/Hadoop/39752.html NewsArticle 《Hadoop权威指南》——3、Hadoop 分布式文件系统, 转载自:http://blog.csdn.net/weixuehao/article/details/16967485 大部分内容转载自以上博客,对某些地方进行了适当的补充。 简介 HDFS (Hadoop D...
相关文章
    暂无相关文章
评论暂时关闭