Hadoop入门介绍

来源:互联网 发布:安卓远程录音源码 编辑:程序博客网 时间:2024/06/07 06:22

Hadoop这个名字不是一个缩写,它是一个虚构的名字。该项目的创建者,Doug Cutting如此解释Hadoop的得名:"这个名字是我孩子给一个棕黄色的大象样子的填充玩具命名的。我的命名标准就是简短,容易发音和拼写,没有太多的意义,并且不会被用于别处。小孩子是这方面的高手。Google就是由小孩命名的。

    Hadoop 是一个能够对大量数据进行分布式处理的软件框架。但是 Hadoop 是以一种可靠、高效、可伸缩的方式进行处理的。Hadoop 是可靠的,因为它假设计算元素和存储会失败,因此它维护多个工作数据副本,确保能够针对失败的节点重新分布处理。Hadoop 是高效的,因为它以并行的方式工作,通过并行处理加快处理速度。Hadoop 还是可伸缩的,能够处理 PB 级数据。此外,Hadoop 依赖于社区服务器,因此它的成本比较低,任何人都可以使用。

  Hadoop带有用 Java 语言编写的框架,因此运行在 Linux 生产平台上是非常理想的。Hadoop 上的应用程序也可以使用其他语言编写,比如 C++。

     Hadoop 有许多元素构成。其最底部是 Hadoop Distributed File System(HDFS),它存储 Hadoop 集群中所有存储节点上的文件。HDFS(对于本文)的上一层是 MapReduce 引擎,该引擎由 JobTrackers 和 TaskTrackers 组成。

    Hadoop由以下几个项目构成

总体结构图如下

1、Hadoop Common :Hadoop体系最底层的一个模块,为Hadoop各子项目提供各种工具,如:配置文件和日志操作等。

2、HDFS:分布式文件系统,提供高吞吐量的应用程序数据访问,对外部客户机而言,HDFS 就像一个传统的分级文件系统。可以创建、删除、移动或重命名文件,等等。但是 HDFS 的架构是基于一组特定的节点构建的(参见图 1),这是由它自身的特点决定的。这些节点包括 NameNode(仅一个),它在 HDFS 内部提供元数据服务;DataNode,它为 HDFS 提供存储块。由于仅存在一个 NameNode,因此这是 HDFS 的一个缺点(单点失败)。

  存储在 HDFS 中的文件被分成块,然后将这些块复制到多个计算机中(DataNode)。这与传统的 RAID 架构大不相同。块的大小(通常为 64MB)和复制的块数量在创建文件时由客户机决定。NameNode 可以控制所有文件操作。HDFS 内部的所有通信都基于标准的 TCP/IP 协议。

3、MapReduce :一个分布式海量数据处理的软件框架集计算集群。 

4、Avro :doug cutting主持的RPC项目,主要负责数据的序列化。有点类似Google的protobuf和Facebook的thrift。avro用来做以后hadoop的RPC,使hadoop的RPC模块通信速度更快、数据结构更紧凑。

5、Hive :类似CloudBase,也是基于hadoop分布式计算平台上的提供data warehouse的sql功能的一套软件。使得存储在hadoop里面的海量数据的汇总,即席查询简单化。hive提供了一套QL的查询语言,以sql为基础,使用起来很方便。

6、Hbase :基于Hadoop Distributed File System,是一个开源的,基于列存储模型的可扩展的分布式数据库,支持大型表的存储结构化数据。

7、Pig :是一个并行计算的高级的数据流语言和执行框架 ,SQL-like语言,是在MapReduce上构建的一种高级查询语言,把一些运算编译进MapReduce模型的Map和Reduce中,并且用户可以定义自己的功能。

8、ZooKeeper :Google的Chubby一个开源的实现。它是一个针对大型分布式系统的可靠协调系统,提供的功能包括:配置维护、名字服务、分布式同步、组服务等。ZooKeeper的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。

9、Chukwa :一个管理大型分布式系统的数据采集系统 由yahoo贡献。

10、Cassandra :无单点故障的可扩展的多主数据库

11、Mahout :一个可扩展的机器学习和数据挖掘库

HDFS:(Hadoop Distributed File System)分布式文件系统,提供高吞吐量的应用程序数据访问,对外部客户机而言,HDFS 就像一个传统的分级文件系统。可以创建、删除、移动或重命名文件,等等。但是 HDFS 的架构是基于一组特定的节点构建的,这是由它自身的特点决定的。这些节点包括 NameNode(仅一个),它在 HDFS 内部提供元数据服务;DataNode,它为 HDFS 提供存储块。由于仅存在一个 NameNode,因此这是 HDFS 的一个缺点(单点失败)。

    存储在 HDFS 中的文件被分成块,然后将这些块复制到多个计算机中(DataNode)。这与传统的 RAID 架构大不相同。块的大小(通常为 64MB)和复制的块数量在创建文件时由客户机决定。NameNode 可以控制所有文件操作。HDFS 内部的所有通信都基于标准的 TCP/IP 协议。

    HDFS基本概念介绍

    1、Block:HDFS默认的基本存储单位是64M的数据块,和普通文件系统相同的是,HDFS中的文件是被分成64M一块的数据块存储的。 不同于普通文件系统的是,HDFS中,如果一个文件小于一个数据块的大小,并不占用整个数据块存储空间。

    2、元数据节点(NameNode)和数据节点(DataNode)

    元数据节点保存内容:

        a、主要用来管理文件系统的命名空间,其将所有的文件和文件夹的元数据保存在一个文件系统树中。 这些信息也会在硬盘上保存成以下文件:命名空间镜像(namespace image)及修改日志(edit log)

        b、其还保存了一个文件包括哪些数据块,分布在哪些数据节点上。然而这些信息并不存储在硬盘上,而是在系统启动的时候从数据节点收集而成的。

    数据节点保存内容

        真正存储数据的地方。客户端(client)或者元数据信息(namenode)可以向数据节点请求写入或者读出数据块。 其周期性的向元数据节点回报其存储的数据块信息。

    3、从元数据节点(secondary namenode)

    从元数据节点并不是元数据节点出现问题时候的备用节点,它和元数据节点负责不同的事情。 其主要功能就是周期性将元数据节点的命名空间镜像文件和修改日志合并,以防日志文件过大。这点在下面会相信叙述。 合并过后的命名空间镜像文件也在从元数据节点保存了一份,以防元数据节点失败的时候,可以恢复。

HDFS是一个不错的分布式文件系统,它有很多的优点,但也存在有一些缺点。目前而言,它在以下几个方面就效率不佳:
低延时访问
HDFS不太适合于那些要求低延时(数十毫秒)访问的应用程序,因为HDFS是设计用于大吞吐量数据的,这是以一定延时为代价的。HDFS是单Master的,所有的对文件的请求都要经过它,当请求多时,肯定会有延时。当前,对于那些有低延时要求的应用程序,HBase是一个更好的选择。现在HBase的版本是0.20,相对于以前的版本,在性能上有了很大的提升,它的口号就是goes real time。
使用缓存或多master设计可以降低client的数据请求压力,以减少延时。还有就是对HDFS系统内部的修改,这就得权衡大吞吐量与低延时了,HDFS不是万能的银弹。
大量小文件
因为Namenode把文件系统的元数据放置在内存中,所以文件系统所能容纳的文件数目是由Namenode的内存大小来决定。一般来说,每一个文件、文件夹和Block需要占据150字节左右的空间,所以,如果你有100万个文件,每一个占据一个Block,你就至少需要300MB内存。当前来说,数百万的文件还是可行的,当扩展到数十亿时,对于当前的硬件水平来说就没法实现了。还有一个问题就是,因为Map task的数量是由splits来决定的,所以用MR处理大量的小文件时,就会产生过多的Maptask,线程管理开销将会增加作业时间。举个例子,处理10000M的文件,若每个split为1M,那就会有10000个Maptasks,会有很大的线程开销;若每个split为100M,则只有100个Maptasks,每个Maptask将会有更多的事情做,而线程的管理开销也将减小很多。
要想让HDFS能处理好小文件,有不少方法:
1、利用SequenceFile、MapFile、Har等方式归档小文件,这个方法的原理就是把小文件归档起来管理,HBase就是基于此的。对于这种方法,如果想找回原来的小文件内容,那就必须得知道与归档文件的映射关系。
2、横向扩展,一个Hadoop集群能管理的小文件有限,那就把几个Hadoop集群拖在一个虚拟服务器后面,形成一个大的Hadoop集群。google也是这么干过的。
3、多Master设计,这个作用显而易见了。正在研发中的GFS II也要改为分布式多Master设计,还支持Master的Failover,而且Block大小改为1M,有意要调优处理小文件啊。
附带个Alibaba DFS的设计,也是多Master设计,它把Metadata的映射存储和管理分开了,由多个Metadata存储节点和一个查询Master节点组成。
多用户写,任意文件修改
目前Hadoop只支持单用户写,不支持并发多用户写。可以使用Append操作在文件的末尾添加数据,但不支持在文件的任意位置进行修改。这些特性可能会在将来的版本中加入,但是这些特性的加入将会降低Hadoop的效率,就拿GFS来说吧,这篇文章里就说了google自己的人都用着Multiple Writers很不爽。
利用Chubby、ZooKeeper之类的分布式协调服务来解决一致性问题。

在测试Hadoop时, 使用NameNode身上的dfshealth.jsp管理页面发现,DataNode在运行的过程中,Last Contact参数时常会超过3。LC(Last Contact)的意思是表明DataNode有多少秒的时间未向NameNode发送心跳包了。然而默认DataNode是3秒发送一次,我们都知道,NameNode默认以10分钟作为DN的死亡超时时间,那么究竟有哪些因素会导致JSP管理页面LC参数超过3,甚至会达到200以上,这样的情况对我们的系统的稳定运行究竟有没有影响?
事实上,这现象我观察了好一阵子,影响LC参数增大的原因有下面几种情况:
1.HDFS收到大量删除BLOCK的命令. 请参见:https://issues.apache.org/jira/browse/HDFS-611
2.HDFS 有大量BLOCK需要report 给NN;
3.组织心跳包的数据;
4.网络环境。
前两种情况LC的值一般不会超过100,对性能不会造成很大影响。 Hadoop-0.22.0 以后版本,Hadoop也有所改进。
那么值的一提的是DN在组织心跳包期间,对FSDatasetInterface 接口进行了相关方法的调用,具体可以参考一下FSDatasetMBean接口中的几个方法:
[java] view plain copy
  1. /** 
  2.    * Returns the total space (in bytes) used by dfs datanode 
  3.    * @return  the total space used by dfs datanode 
  4.    * @throws IOException 
  5.    */    
  6.   public long getDfsUsed() throws IOException;  
  7.       
  8.   /** 
  9.    * Returns total capacity (in bytes) of storage (used and unused) 
  10.    * @return  total capacity of storage (used and unused) 
  11.    * @throws IOException 
  12.    */  
  13.   public long getCapacity() throws IOException;  
  14.   
  15.   /** 
  16.    * Returns the amount of free storage space (in bytes) 
  17.    * @return The amount of free storage space 
  18.    * @throws IOException 
  19.    */  
  20.   public long getRemaining() throws IOException;  


这三个方法意思大家都很明白,它们的实现者分别为DF,DU两个类,它们会不定期的通过Shell类的runComamnd方法来执行系统命令,以获取当前目录的 df, du 值。
然而在执行的过程当中有趣的事情发生了,笔者有13个分区,一共存有14万多个BLOCK,
Df 和du 平均每次执行的时间都会超过两秒,戏剧性的是DU 和DF最高的一次在执行某分区目录的命令时,居然用了180秒以上。(Shell#runCommand方法中, 从ProcessBuilder 实例化到process.start() 执行时间)。
难道是分区目录下的BLOCK数量过多导致运行缓慢么,在linux 系统里执行DF DU相同的命令结果都是以毫秒时间结束。那问题显然出在了ProcessBuilder, 居了解,该类由JVM通过Linux 内核来fork 子进程,子进程当然会完全继承父进程的所有内存句柄,jstack看到JVM此时线程状态大部分处于WAITING, 这个过程经过测试确实会影响DFSClient写入超时,或关闭流出错(下篇会说到, 作为长久Running 的DFSClient, 应该做好流的关闭工作,0.21-trunk中流的关闭仍然存有安全隐患。) 最后我折腾过从32位机子一路换到64位的机子,但问题依然存在。
最后只好再次对HDFS开刀,重构了DU,DF 以及自己的IOStat , Uptime类,通过Linux系统来执行,把结果输出到临时文件中,然后由Hadoop来读取。 LC的问题不再发生。
  • HDFS中元数据中是否有冗余?如果有冗余那么冗余机制是什么?冗余写入过程是什么?
  • HDFS中元数据是否有读写权限?如果有权限,通过什么方式控制权限?
  • 客户端与元数据是否存在同步问题,如果存在那么如何同步?
  • 是否有元数据锁?是否支持entry锁? 

1、HDFS 和 KFS 简介

两者都是GFS的开源实现,而HDFS 是Hadoop 的子项目,用Java实现,为Hadoop上层应用提供高吞吐量的可扩展的大文件存储服务。

Kosmos filesystem(KFS) is a high performance distributed filesystem for web-scale applications such as, storing log data, Map/Reduce data etc. It builds upon ideas from Google‘s well known Google Filesystem project. 用C++实现

本文选取的源码版本如下:

hadoop-0.17.2.1

Kfs 0.2.2

2、HDFS和KFS体系架构

图1 体系架构

HDFS和KFS都属于分布式文件系统,它们的元数据管理采用集中式方式实现,数据实体先分片然后分布式存储。本文先介绍这类系统的模块组成以及各模块的关键技术,并以此为线索分析和比较HDFS的异同点。

HDFS和KFS大致有以下几个模块组成:

MetaServer:

Namespace 管理

Layout管理

MetaImage管理

Lease管理

ChunkServer:

Chunk管理

Chunk存储

Client Transaction Layer,该部分是系统给上层应用提供的接口,本文不予比较。

3、HDFS和KFS各模块的关键技术

HDFS和KFS关键实现技术如下:

MetaServer:

Namespace的组织和维护

MetaData的序列化和加载

系统恢复

Chunk Layout的ChunkServer选择

Lease的管理和维护

ChunkServer:

Chunk存储组织

本地Chunk 信息的重建

Chunk失效处理

Client Transaction:文件操作

4、HDFS和KFS MetaServer实现的比较(1)

Namespace的组织和维护

HDFS Namespace的组织采用Component模式,文件夹、文件和Chunk组成如下层次结构。

Root /------|

   |-----/terry---|---/sub0

                                      |----file3---|---block0

                                                        |---block1

                   |-----/adam--|---/sub0

       |-------file0

                                                                 | --block2

                   |-------tmpfile1

     |---block3

                                      |---block4

KFS采用B+树存放文件系统的结点信息,各结点存有父结点的索引,从而实现文件夹、文件和Chunk的层次关系。

5、HDFS和KFS MetaServer实现的比较(2)

LayoutManagement实现,包括Chunk Server选择算法、负载均衡实现。

Chunk Server选择算法包括以下:

Chunk 创建时,Chunk Server的选择;

Chunk 实际拷贝数与需求不一致时,Chunk的重拷贝和删除问题。

写入的ChunkServer具备的基本条件如下:

节点处于活跃期;

节点有Chunk读(拷贝源节点)或写(拷贝目标节点)并发的余量;

节点网络流量小于系统平均流量的两倍;

作为存储点,节点有存储余量;

Chunk在该节点所属Rack上的拷贝数没到上限;

基本原则:HDFS优先保证前3份拷贝有两份在一个Rack上,另一份在不同的Rack上;而KFS要求拷贝均匀分散在不同的Rack上。

Chunk创建时,第一个存储点的选择问题:

当创建Chunk的Client上部署有Chunk Server时,HDFS和KFS均优先选择该节点为首存储点;

否则,HDFS随机选择,KFS优先选择存储和网络负载较轻的节点。

根据上述基本原则选择其余节点。

拷贝数小于需求时,HDFS根据基本原则选择备用节点;KFS优先选择失效节点相同Rack上的节点;

拷贝数大于需求时,HDFS根据基本原则删除多余的Location;KFS优先考虑拷贝的均匀分布,然后再根据节点的负载选择失效拷贝。

6、HDFS和KFS MetaServer实现的比较(3)

MetaServer根据Namespace中的chunk列表,将列表乱序,依此扫描chunk location信息,将存储或网络负载超过阈值的节点上的拷贝标志为失效,并转存到负载较低的节点上。

负载控制方面:HDFS任务分配较KFS精细;HDFS实现上有网络流量控制,KFS没有。

实现方式上:HDFS使用多线程实现多任务并发执行,而KFS使用Reactor模式实现多任务并发。

7、HDFS和KFS MetaServer实现的比较(4)

Meta Image Management,包括FSImage和操作日志两部分。

HDFS FSImage结构如图2(新版本中删除了DataNode Image部分)。

图2 HDFS FSImage

KFS存储元数据B+树的叶子节点信息到磁盘上,并记录该镜像加载过程中需要合并的操作日志文件名。

HDFS通过多目录的同时备份,并记录checkpoint时间。系统重启时,通过检查各目录下镜像信息以及中间文件存在状态,采取合理的策略恢复元数据信息,并生成新的元数据镜像。

KFS在本地存有不同版本的镜像和操作日志,并通过一个硬链接指向最新的镜像信息。启动时,加载硬链接指向的镜像文件,以及镜像中存有的操作日志及其之后的所有的操作日志,恢复元数据。

8、HDFS和KFS MetaServer实现的比较(5)

Lease的管理和维护-1

HDFS和KFS的锁管理通过Lease方式来实现,并且都在Chunk级别加锁。

HDFS仅对正在创建中文件拥有的Chunk加锁,即只有写锁。并且文件删除过程中,直接清除该文件上所有的锁,使Lease renew操作失败,中断用户的写操作。

KFS实现了读和写两种锁机制,可以多用户并发读,单用户独占写,读写互斥。已加锁的文件删除时,将文件移动到Namespace的dumpster目录,待有锁清除操作时,检查相关文件的锁信息,将无锁的文件彻底删除。

HDFS实现的是实名锁,记录了客户端信息;KFS采用的是匿名锁,仅记录了分配的Lease ID。

Lease的管理和维护-2

HDFS中ChunkServer没有锁标志,MetaServer将写锁分配给Client,由Client刷新;

KFS的实现相对复杂些。

写操作,MetaServer分配Chunk时,给Main ChunkServer分配writer-Lease,ChunkServer接收到Client的写操作时检查并Renew该Lease;

读操作,MetaServer给Client分配Reader-Lease,由Client根据读的进度进行Lease的Renew操作;

Lease的销毁有两种方式:

定时器

特定的操作关联删除

锁机制实现上,KFS相对完善些,但其匿名锁方式也可能存在隐患。

9、HDFS和KFS ChunkServer实现的比较(1)

ChunkServer上Chunk的存储组织:

l         HDFS和KFS都可以配置多个存储目录;

l         在存储目录存储空间配额允许的情况下,HDFS按照轮转的方式将Chunk均匀的放置到各存储目录;KFS按照ChunkId和存储目录个数的模运算选择存放目录。

l         ChunkId由MetaServer统一分配,HDFS的放置方式较KFS均匀,chunk维护的过程中,要维护chunk到文件的映射。KFS的放置策略简单,Chunk和文件之间的映射关系直接,但弊端也十分明显,配置文件中的存储目录数目不能修改,否则系统将无法正常运作。KFS0.2.2中似乎并没有解决这个问题。

l         在同一个存储目录中,HDFS每级目录最多64个Chunk和64个子目录,组成层次结构。存放时Chunk时,要求嵌套目录的深度尽量小。KFS采用平面结构,所有Chunk存放在一个目录下。根据底层文件系统实现机制,HDFS Chunk文件的定位速度较KFS快。

l         HDFS各工作目录有文件锁,避免多网元共享存储目录引发错误;KFS没有该保护机制。

10、HDFS和KFS ChunkServer实现的比较(2)

ChunkServer上Chunk存储:

l         HDFS中,每个Chunk存放两个文件,实体数据和Meta数据;KFS存放为一份文件,Meta数据存放在前16K文件头区域,实体数据存放在16k之后。

l         HDFS和KFS默认的Chunk大小为64M。Meta校验码部分均采用Adler_32算法。 HDFS根据配置,决定是否计算校验码,以及校验块的大小。 KFS每16K数据计算一个32位校验码,存放在对应的Meta数据区域。

l         KFS有16K的文件头,在实现Truncate操作时,KFS0.2.2版本中似乎忽略了这部分数据,Bug or not?

11、HDFS和KFS ChunkServer实现的比较(3)

本地Chunk 信息的重建:

l         HDFS和KFS均通过扫描本地工作目录,重建内存中的Chunk管理数据;

l         HDFS在ChunkServer中没有Chunk镜像和操作日志记录;KFS中有这部分实现,在ChunkServer上存储Chunk镜像信息和操作日志,并实现了启动时对镜像和操作日志的加载功能。但是这部分代码没有调用,也许废弃了。

12、HDFS和KFS ChunkServer实现的比较(4)

Chunk失效处理

l         HDFS:ChunkServer通过定期的Heartbeat向MetaServer汇报本地Chunk列表,或者完成Chunk写操作后,向MetaServer汇报新写入的Chunk信息。MetaServer根据状态,向ChunkServer分发Chunk复制任务或者Chunk失效信息等。HDFS接收到失效信息后,删除Chunk文件;

l         KFS:启动时或者在读操作ChunkSum错误时,向MetaServer汇报Chunk信息。MetaServer删除Chunk有两类操作:Delete和Stale。前者由Client触发,后者由ChunkServer汇报错误触发。Delete操作下,ChunkServer直接删除chunk文件;Stale操作下,ChunkServer将Chunk转移到./lost+found目录下。但KFS0.2.2中没有对./lost+found目录中的文件做进一步处理,也许改进版本中会用到。

13、HDFS和KFS Chunk写流程上的区别(1)

HDFS Chunk 写流程,如图3

图3 HDFS Chunk 写流程

14、HDFS和KFS Chunk写流程上的区别(2)

KFS Chunk 写流程,如图4


0 0