Hadoop架构、部署及编程

来源:互联网 发布:dj网络歌手 编辑:程序博客网 时间:2024/06/05 21:55

引言

互联网的发展、数据自动采集器的大范围应用,使信息采集和规模达到空前的水平。Google在2003年发表了”The Google File System”、”MapReduce: SimpliedData Processing on Large Clusters”论文,分别介绍Google 海量数据处理使用的分布式文件系统和计算框架,使大数据时代数据存储和计算发生了革命性的变化。Doug Cutting等人在Nutch项目上吸收了GFS和MapReduce思想并将其演化为Hadoop 项目。经过多年的发展,最终形成了包含多个相关项目的软件生态系统,开创了海量数据处理的新局面。

 

Hadoop是为了解决大数据时代数据存储和处理而设计的。就算没有并行计算程序开发经验的程序员,也可以基于Hadoop容易地开发处并行处理大规模数据的分布式计算程序。

 

目前,国内百度使用Hadoop进行搜索日志的分析和网页数据挖掘、淘宝采用Hadoop系统存储并处理电子商务交易的相关数据、中国移动研究院基于Hadoop的“大云”(BigCloud)系统用于对数据进行分析和并对外提供服务;国外Yahoo! 通过运行Hadoop集群以支持广告系统和Web搜索的研究、Facebook借助运行Hadoop集群支持其数据分析和机器学习。

 

Google十大核心技术

可以说Hadoop两大核心分布式文件系统及分布计算框架脱胎于Google的GFS、MapReduce核心技术。Google作为一个伟大的互联网公司,必定有其杀手锏:Google十项核心技术。这十项核心技术可分为四大类:分布式基础设施、分布式大规模数据处理、分布式数据库技术和数据中心优化技术。

分布式基础设施

GFSChubbyProtocol Buffer

分布式大规模数据处理

 MapReduceSawzall

分布式数据库技术

BigTable、数据库Sharding

数据中心优化技术

数据中心高温化、12V电池、服务器整合

Chubby主要解决锁控制机制,ProtocolBuffer定义数据交换的格式,而Sawzall是一门类型安全的脚本语言,等等。本文重点关注与Hadoop相关的GFS和MapReduce。

 

GFS

搜索引擎需要处理海量的数据,Google两位创始人Larry Page和Sergey Brin在创业初期设计一套名为"BigFiles"的文件系统,而GFS(全称为"Google File System")这套分布式文件系统则是"BigFiles"的延续。Google内部至少运行着200多个GFS集群,最大的集群有几千台服务器,并且服务于多个 Google服务,比如Google搜索。由于GFS主要为搜索而设计,所以不是很适合新的一些Google产品,比YouTube、Gmail和更强调实时性的Caffeine搜索引擎等。因而Google已经在开发下一代GFS,代号为“Colossus”,在设计方面有许多不同,比如:支持分布式Master节点、Chunk节点能支持1MB大小的chunk以支撑低延迟应用的需要。


GFS的架构图

从上图可以看出Client与Chunk节点和Master节点均有交互;与Chunk间主要是进行数据交换,而与master节点间的交互则是查询元数据。

Chunk节点:用来存储数据块,数据文件分割为默认大小64MB,而且每个Chunk有唯一64位标签,每个Chunk都会在整个分布式系统被复制多次,默认为3次。

Master节点:存储与数据文件相关的元数据。元数据包括将64位标签与数据块的位置及其组成文件的表格、数据块副本位置和哪个进程正在读写某个数据块的映射等。Master节点周期性接收每个Chunk节点来的“Heart- beat”,使元数据保持最新状态。

GFS设计特点主要包括:

大文件和大数据块:数据文件的大小普遍在GB级别,而且其每个数据块默认大小为64MB,这样做的好处是减少了元数据的大小,能使Master节点能够非常方便地将元数据放置在内存中以提升访问效率。

操作以添加为主:因为文件很少被删减或者覆盖,通常只是进行添加或者读取操作,这样能充分考虑到硬盘线性吞吐量大和随机读写慢的特点。

支持容错:首先,虽然当时为了设计方便,采用了单Master的方案,但是整个系统会保证每个Master都会有其相对应的复制品,以便于在Master节点出现问题时进行切换。其次,在Chunk层GFS已经在设计上将节点失败视为常态,能非常好地处理Chunk节点失效的问题。

高吞吐量:虽然其单个节点性能无论是从吞吐量还是延迟都很普通,但因为支持上千的节点,所以总的数据吞吐量非常惊人。

保护数据:首先,文件被分割成固定尺寸的数据块以便于保存,而且每个数据块都会被系统复制三份。

扩展能力强:因为元数据偏小,使得1个Master节点能控制上千个Chunk节点。

支持压缩:对于那些稍旧的文件,可以通过对它进行压缩,来节省硬盘空间,并且压缩率非常惊人,有时甚至接近90%。

 MapReduce

MapReduce是源自函数式语言,从MapReduce 自身的命名特点可以看出,MapReduce由两个阶段组成:Map和Reduce,通过Map和Reduce两个步骤来行处理大规模数据集。用户只需编写map() 和reduce() 两个函数,即可完成简单的分布式程序的设计。

Map会先对由很多独立元素组成的逻辑列表中的每一个元素进行指定的操作,会创建多个新的列表来保存Map的处理结果。也就意味着Map操作是高度并行的。


Map过程图

当Map工作完成之后,系统会先对新生成的多个列表进行清理(Shuffle)和排序,之后会这些新创建的列表进行Reduce操作,也就是对一个列表中的元素根据Key值进行适当的合并。


Reduce过程图

 

通过下图对比我们可以看到,Hadoop两大基础部件HDFS和MapReduce就是来源于Google公司的GFS和Google MapReduce。

 

Hadoop

概述

那Hadoop到底是什么呢?Hadoop是Apache软件基金会下面的开源项目,由分布式文件系统和并行执行环境两个子项目构成,该项目的目标是为用户提供便捷地处理海量数据提供平台支持。

自2004年始,Hadoop大事记如下:

2004年-- 最初的版本(现在称为HDFS和MapReduce)由Doug Cutting和Mike Cafarella开始实施。

2005年12月-- Nutch移植新框架,Hadoop在20个节点稳定运行。

2006年01月-- Doug Cutting加入雅虎。

2006年02月-- Apache Hadoop项目正式启动以支持MapReduce和HDFS的独立发展。

2006年02月-- 雅虎的网格计算团队采用Hadoop。

2006年04月-- 标准排序(10 GB每节点)在188节点运行47.9小时。

2006年05月-- 雅虎建立了一个300个节点的Hadoop研究集群。

2006年05月-- 标准排序在500个节点上运行42个小时(硬件配置比4月的更好)。

2006年11月-- 研究集群增加到600个节点。

2006年12月-- 标准排序在20个节点上运行1.8个小时,100个节点3.3小时,500个节点5.2小时,900个节点7.8个小时。

2007年01月-- 研究集群到达900个节点。

2007年04月-- 研究集群达到两个1000个节点的集群。

2008年04月-- 赢得世界最快1 TB数据排序,在900个节点上用时209秒。

2009年03月-- 17个集群总共24 000台机器。

2009年04月--59秒内排序500 GB(在1400个节点上)和173分钟内排序100 TB数据(在3400个节点上)。

2011年12月27日--1.0.0版本推出。标志着Hadoop已经初具生产规模。

2013年2月,Wandisco推出了世界第一款可用于实际业务环境的Apache Hadoop 2 -WANdisco Distro(WDD)

Hadoop特点主要包括:

扩容能力(Scalable):能可靠地(reliably)存储和处理千兆字节(PB)数据。

成本低(Economical):可以通过普通机器组成的服务器群来分发以及处理数据。这些服务器群总计可达数千个节点。

高效率(Efficient):通过分发数据,hadoop可以在数据所在的节点上并行(parallel)处理,这使得处理非常的快速。

可靠性(Reliable):hadoop能自动地维护数据的多份复制,并且在任务失败后能自动地重新部署(redeploy)计算任务。

 

HDFS分布式文件系统

HDFS被设计成适合运行在通用硬件(commodity hardware)上的分布式文件系统。为做到可靠性而,HDFS创建了多份数据块的复制,并放置在服务器群的计算节点,MapReduce就可以在它们所在的节点上处理这些数据了。


HDFS可以存储并管理PB级数据、处理非结构化数据、注重数据处理的吞吐量,设计时假设没有文件并发写入,因而是write-once-read-many存取模式;同时,将节点失效视为常态,即任何一个节点失效,不影响服务,可以自动完成副本的复制,不建议存储小文件和大量的随机读,不支持文件写入。

HDFS是一个的主从结构,一个HDFS集群是有一个名字节点,它是一个管理文件元数据,以及响应客户端访问文件的主服务器,存储文件元数据,如文件目录结构,文件属性,以及每个文件的块列表以及块所在数据节点;数据节点在本地文件系统存储文件块数据,以及块数据的校验和。HDFS文件切分成块(默认大小64M),以块为单位,每个块有多个副本存储在不同的机器上,副本数可在文件生成时指定(默认3)。HDFS可以创建、删除、移动或重命名文件,当文件创建、写入和关闭之后不能修改文件内容。

HDFS系统架构图

 

HDFS主要组件包括名字节点和数据节点,其定位和比较如下:

NameNode

DataNode

存储元数据

存储文件内容

元数据保存在内存中

文件内容保存在磁盘

保存文件,block ,datanode之间的映射关系

维护了block id到datanode本地文件的映射关系

名字节点是中心服务器,为单一节点(简化系统的设计和实现),负责管理文件系统的名字空间(namespace)以及客户端对文件的访问,负责文件元数据的操作,数据节点负责处理文件内容的读写请求,跟文件内容相关的数据流不经过名字节点,只会询问它跟那个数据节点联系,否则名字节点会成为系统的瓶颈。副本存放在数据节点上由名字节点来控制,根据全局情况做出块放置决定,读取文件时名字节点尽量让用户先读取最近副本,降低带宽消耗和读取时延。名字节点全权管理数据块的复制,它周期性地从集群中的每个数据节点接收心跳信号和块状态报告(Blockreport)。接收到心跳信号意味着该数据节点节点工作正常。块状态报告包含了一个该数据节点上所有数据块的列表。

MapReduce编程框架

多年来磁盘存储容量快速增加的同时,其访问速度却未能与时俱进。读取磁盘所有数据需要更长时间。

摩尔定律:当价格不变时,集成电路上可容纳的晶体管数目,约每隔18个月便会增加一倍,性能也将提升一倍。换言之,每一美元所能买到的电脑性能,将每隔18个月翻两倍以上。从1971年至2008年,“晶体管/芯片”增长>100,000倍。

克来德法则(Kryder's Law)说的是每10.5年硬盘驱动器的信息密度就要增长1000倍,也就是说,每13个月存储密度就要翻一番。从1956年至2008年,磁盘密度增长了100,000,000倍。而巨大的例外是,磁盘速度从1956年每分钟1200次到现在的每分钟转速15000次,54年仅仅增长了12.5倍。

在这磁盘速度成为系统性能瓶颈的时候,分布式计算应运而生。

MapReduce核心思想是分而治之,利用HDFS分布式数据存储将计算分布在集群中不同的数据节点。MapReduce编程框架具有自动实现分布式并行计算、容错性强、提供状态监控工具、模型抽象简洁等特点。其原理是利用输入key/value pair集合来产生输出的key/value pair集合。Map函数接受输入的key/value pair值,然后产生中间key/value pair值的集合;Reduce函数接受中间key值和相关的value值的集合,合并这些value值。


MapReduce框架图

 

当Map开始产生输出时,并不是简单的将数据写入磁盘,因为频繁的磁盘操作会导致性能严重下降。他的处理过程更复杂,数据首先是写入内存中的一个缓冲区,并进行预排序,以提升效率。每个Map任务都有一个用来写入输出数据的循环内存缓冲区,默认大小为100MB。

如果设定了Combiner,将在排序输出的基础上运行。Combiner就是一个Mini Reducer,它在执行Map任务的节点本身运行,先对Map的输出做一次简单Reduce,使得Map的输出更紧凑,更少的数据会被写入磁盘和传送给Reducer。

Map的输出文件放置在Map任务的TaskTracker的本地磁盘上,它是运行Reduce任务的TaskTracker所需要的输入数据。Reduce任务的输入数据分布在集群内的多个Map任务的输出中,Map任务可能会在不同的时间内完成,只要有其中的一个Map任务完成,Reduce任务就开始拷贝它的输出。Reduce任务拥有多个拷贝线程,可以并行的获取Map输出,线程数默认是5。

拷贝来的数据叠加在磁盘上,有一个后台线程会将它们归并为更大的排序文件,节省后期归并的时间。当所有的Map输出都被拷贝后,Reduce人物进入排序阶段,这个阶段会对所有的Map输出进行归并排序,这个工作会重复多次。


MapReduce运行过程图

 

对于程序员来说,我们只是实现map()和reduce()函数,剩下的由框架完成。举个MapReduce编程中HelloWorld的例子:WordCount

源数据:

Page 1: the weather is good

Page 2: today is good

Page 3: good weather is good


map输出:

Worker 1:

(the 1), (weather 1), (is 1), (good 1)

Worker 2:

(today 1), (is 1), (good 1)

Worker 3:

(good 1), (weather 1), (is 1), (good 1)


Reduce的输入:

Worker1:

(the 1)

Worker 2:

(is 1), (is 1), (is 1)

Worker 3:

(weather 1), (weather 1)

Worker 4:

(today 1)

Worker 5:

(good 1), (good 1), (good 1), (good 1)

 

Reduce输出:

Worker1:

(the 1)

Worker 2:

(is 3)

Worker 3:

(weather 2)

Worker 4:

(today 1)

Worker 5:

(good 4)


要完成Map操作,Map函数实现过程如下:

public static class Map

           extends Mapper<LongWritable, Text, Text, IntWritable>{

 

   private final static IntWritable one = new IntWritable(1); // type ofoutput value

   private Text word = new Text();  // type of output key

     

   public void map(LongWritable key, Text value, Context context

                    ) throws IOException,InterruptedException {

     StringTokenizer itr = new StringTokenizer(value.toString()); // line tostring token

     

     while (itr.hasMoreTokens()) {

       word.set(itr.nextToken());    //set word as each input keyword

       context.write(word, one);     //create a pair <keyword, 1>

     }

}


Reduce函数实现如下:

public static class Reduce

      extends Reducer<Text,IntWritable,Text,IntWritable> {

 

   private IntWritable result = new IntWritable();

 

   public void reduce(Text key, Iterable<IntWritable> values,

                       Context context

                       ) throws IOException,InterruptedException {

     int sum = 0; // initialize the sum for each keyword

     for (IntWritable val : values) {

       sum += val.get(); 

     }

     result.set(sum);

 

     context.write(key, result); // create a pair <keyword, number ofoccurences>

}

 

驱动函数:

public static void main(String[] args)throws Exception {

   Configuration conf = new Configuration();

   String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();// get all args

   if (otherArgs.length != 2) {

     System.err.println("Usage: WordCount <in> <out>");

     System.exit(2);

    }

 

   // create a job with name "wordcount"

   Job job = new Job(conf, "wordcount");

   job.setJarByClass(WordCount.class);

   job.setMapperClass(Map.class);

   job.setReducerClass(Reduce.class);

  

   // uncomment the following line to add the Combiner

   job.setCombinerClass(Reduce.class);

    

 

   // set output key type  

   job.setOutputKeyClass(Text.class);

   // set output value type

   job.setOutputValueClass(IntWritable.class);

   //set the HDFS path of the input data

   FileInputFormat.addInputPath(job, new Path(otherArgs[0]));

   // set the HDFS path for the output

   FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));

 

   //Wait till job completion

   System.exit(job.waitForCompletion(true) ? 0 : 1);

  }

 

Task Job

Hadoop中的所有MapReduce程序均以Job形式提交给集群运行。一个MapReduceJob会被划分为若干个Map Task和Reduce Task并行执行。JobTracker一直在等待JobClient提交作业

TaskTracker每隔3秒向JobTracker发送心跳heartbeat询问有没有任务可做,如果有,让其派发任务给它执行,这是pull过程: slave主动向master拉生意

MapReduce应用场景

日志分析、排序、搜索、广告计算,广告优化、分析,点击流分析,链接分析

搜索关键字进行内容分类、搜索引擎,创建索引

word 计数,统计、过滤、分析、查询

垃圾数据分析、数据分析、机器学习、数据挖掘

大规模图像转换(纽约时报使用Hadoop 和EC2在36小时内将4TB的TIFF图像,包括405K大TIFF图像,3.3M SGML文章和405K XML文件转换为800K适合在Web上使用的PNG图像)

Hadoop生态系统

HDFS:Hadoop DistributedFile System,Hadoop 分布式文件系统是Hadoop 体系中数据存储管理的基础。它是一个高度容错的系统,能检测和应对硬件故障,用于在低成本的通用硬件上运行。HDFS 简化了文件的一致性模型,通过流式数据访问,提供高吞吐量应用程序数据访问功能,适合带有大型数据集的应用程序。

MapReduce: 是一种计算模型,用以进行大数据量的计算。Hadoop的MapReduce 实现,和Common、HDFS 一起,构成了Hadoop 发展初期的三个组件。MapReduce 将应用划分为Map 和Reduce 两个步骤,其中Map 对数据集上的独立元素进行指定的操作,生成键- 值对形式中间结果。Reduce 则对中间结果中相同“键”的所有“值”进行规约,以得到最终结果。MapReduce 这样的功能划分,非常适合在大量计算机组成的分布式并行环境里进行数据处理。

HBase:Google发表了BigTable系统论文后,开源社区就开始在HDFS上构建相应的实现Hbase。Hbase是一个针对结构化数据的可伸缩、高可靠、高性能、分布式和面向列的动态模式数据库。和传统关系数据库不同,Hbase采用了BigTable的数据结构:增强的稀疏排序映射表(Key/Value),其中,键由行关键字、列关键字和时间戳构成。Hbase提供了对大规模数据的随机、实时读写访问,同时,HBase中保存的数据可以使用MapReduce 来处理,它将数据存储和并行计算完美地结合在一起。

Hive :Hadoop 中的一个重要子项目,最早由Facebook设计,是建立在Hadoop 基础上的数据仓库架构,它为数据仓库的管理提供了许多功能,包括:数据ETL(抽取、转换和加载)工具、数据存储管理和大型数据集的查询和分析能力。Hive 提供的是一种结构化数据的机制,定义了类似于传统关系数据库中的类SQL 语言:Hive QL,通过该查询语言,数据分析人员可以很方便地运行数据分析业务。

Pig: 运行在Hadoop 上,是对大型数据集进行分析和评估的平台。它简化了使用Hadoop进行数据分析的要求,提供了一个高层次的、面向领域的抽象语言:Pig Latin。通过Pig Latin,数据工程师可以将复杂且相互关联的数据分析任务编码为Pig 操作上的数据流脚本,通过将该脚本转换为MapReduce 任务链,在Hadoop 上执行。和Hive 一样,Pig 降低了对大型数据集进行分析和评估的门槛。

Mahout: 起源于2008 年,最初是ApacheLucent 的子项目,它在极短的时间内取得了长足的发展,现在是Apache 的顶级项目。Mahout 的主要目标是创建一些可扩展的机器学习领域经典算法的实现,旨在帮助开发人员更加方便快捷地创建智能应用程序。Mahout 现在已经包含了聚类、分类、推荐引擎(协同过滤)和频繁集挖掘等广泛使用的数据挖掘方法。除了算法,Mahout 还包含数据输入/ 输出工具、与其他存储系统(如数据库、MongoDB 或Cassandra)集成等数据挖掘支持架构。

Avro、 Flume、 X-RIME、Crossbow、Chukwa、Sqoop、Oozie、 ZooKeeper、 Karmasphere……

 

Hadoop部署

Hadoop 支持 Linux 及 Windows 操作系统, 但其官方网站声明 Hadoop的分布式操作在 Windows 上未做严格测试,建议只把Windows 作为Hadoop 的开发平台。在Windows 环境上的安装步骤如下( Linux 平台类似,且更简单一些):

安装Java 1.6.x,并将JAVA_HOME 环境变量设置为Java 的安装根目录如C:\Program Files\Java\jdk1.6.0_01。

Hadoop 官方网站 http://hadoop.apache.org/下载Hadoop Core,将下载后的安装包解压到一个目录,例如解压到c:\hadoop-0.20.1。

修改conf/hadoop-env.sh 文件,在其中设置 JAVA_HOME 环境变量: export JAVA_HOME= "C:\Program Files\Java\jdk1.6.0_01”

 

Hadoop运行模式

单机(非分布式)模式:这种模式在一台单机上运行,没有分布式文件系统,而是直接读写本地操作系统的文件系统。

伪分布式运行模式:这种模式也是在一台单机上运行,但用不同的 Java 进程模仿分布式运行中的各类结点( NameNode, DataNode, JobTracker, TaskTracker, Secondary NameNode)

分布式运行模式


伪分布模式下的WordCount运行情况


通过网页监控MapReduce任务运行情况

 

原创粉丝点击