Hadoop应用实战
上QQ阅读APP看书,第一时间看更新

3.3 Hadoop上的各种其他组件

Hadoop是一个年轻的系统,所以一直有爱好者和程序员们为完善Hadoop系统而开发出各种新的组件。在本节中,我们为大家介绍的这些Hadoop组件都有可能独立成为一个有价值的开源产品,就像Hadoop从Nutch项目中独立出来一样。

我们对每个组件的介绍,其篇幅都是比较短的,而其实每一篇继续展开后都可以再做成一本新的书。本节是为了让读者对这些概念不陌生,当后面介绍实际应用的时候大概知道这些组件的功能。

我们并没有把Hadoop上所有可用的组件都列出来,尽管还有很多组件也是很重要的。有兴趣的同学可以查阅附录C中提供的网站,对Oozie、Sqoop、Ambari、Avro和Zookeeper等其他Hadoop组件的功能和使用方式进行了解。

3.3.1 资源分配系统YARN

YARN(Yet Another Resource Negotiator)是Hadoop上的一个重要的组件,意思是“又一个资源调配器”,它的主要用途就是让其他数据处理引擎能够在Hadoop上顺畅运行。

和YARN的名字所表示的一样,我们可以把YARN理解成一个资源分配器(Resource Manager),它可以分配的内容包括内存和CPU时间,未来还可能包括网络带宽等其他资源。

我们看看如图3-6所示YARN执行路线。

图3-6 YARN执行路线

在Hadoop上使用YARN的步骤如下。

(1)应用程序向YARN提出申请。

(2)YARN请求Namenode上的Node Manager创建一个Application Master实例。

(3)新的Application Master在YARN上注册。

(4)Application Master访问Namenode,得到应用程序需要的文件、数据块的名字和具体位置,计算出运行整个应用程序需要的处理资源。

(5)Application Master从YARN上申请所需的资源。

(6)YARN接受资源申请,把这个申请加入申请队列中。

(7)当Application Master申请的资源可以被使用的时候,YARN批准Application Master实例在指定的数据节点上运行。

(8)Application Master向Namenode节点发送一个CLC(Container Launch Context,容器启动上下文), CLC中包含了应用程序运行所需要的环境变量、安全认证、运行时需要的本地资源以及命令行参数等。

(9)Namenode节点接受申请,并创建一个容器(container)。

(10)当容器的进程开始运行的时候,应用程序就开始运行了。

(11)YARN在应用程序整个运行过程中要保证所有的资源都是可用的,而且如果优先级有变化,YARN会随时中断应用程序的运行。

(12)当所有的任务都完成之后,Application Master把结果发送给应用程序,并解除其在YARN上的注册。

如果在YARN上运行的是一个MapReduce任务,那么Application Master会在所有的map任务都完成之后,再申请reduce任务所需要的资源来处理map任务产生的中间结果。

在YARN上可以运行的不只是MapReduce,可以是为Hadoop设计的任何程序,比如Apache Storm。

技术的变化是非常快的,在我们写这本书的过程中,Hadoop生态圈又发生了变化,Mesos和Kubernetes逐渐占据优势,YARN被边缘化,有兴趣的同学,可以参见我们在附录中列出来的网站了解相关的细节。

3.3.2 灵活的编程语言pig

SQL语言是一种描述性的语言,而这对程序员来说功能是不够的。他们更加希望能够在作查询的同时还做一些数据处理工作,甚至改动一些数据,于是pig组件应运而生。pig是下面两个产品的组合。

(1)类似SQL的描述性查询语言;

(2)过程性的编程语言。

那么这个组件为什么会叫pig(猪)这么有趣的一个名字呢?在Apache基金会的pig项目主页上,是这么说的。

(1)Pigs Eat Anything(猪会吃任何东西)。也就是说pig组件可以用来处理任何数据,无论是结构化、非结构化还是嵌套的数据。

(2)Pigs Live Anywhere(猪可以住在任何地方),也就是说pig组件虽然是因Hadoop而生,但它却可以在任何框架中使用。

(3)Pigs Are Domestic Animals(猪是家养的动物),也就是说pig组件的易用性非常好。

(4)Pigs Fly(猪会飞),这个说法很有意思,即pig的程序员不想让pig组件有太多的负担,不然就飞不起来了。

pig有两个组成部分。

(1)pig上的编程语言,Pig latin(pig拉丁语)。

(2)能够翻译Pig latin的编译器:把用Pig latin写的代码转换成可执行的代码。

pig支持4种类型的函数。

(1)计算函数(Eval)。比如用来计算平均值的AVG函数、计算一个数据包中最小项的MIN函数等。

(2)过滤函数(Filter)。用来消除在运算中不需要的行,比如检查数据包是否为空的IsEmpty函数。

(3)加载函数(Load)。用来加载来自外部存储的数据,比如加载纯文本格式的TextLoader函数。

(4)存储函数(Store)。用来把内容存储到外部存储,比如把关系存储到二进制文件的BinStorage函数。

pig和SQL对比,它的优势在于可以轻松处理大规模数据集,而且处理方式要灵活得多。

在pig上有4种基本数据格式。

(1)Atom。和数据库中的Field(字段)基本是一致的,可以是任何字符串或者数字。

(2)Tuple。一系列Atom组成的记录,和数据库中的Record(记录)基本一致。

(3)Bag。一些Tuple的集合,在集合中的记录都是唯一性的。

(4)Map。一些Key-Value组的集合。

我们用图3-7、图3-8来看这些数据格式具体形式。

图3-7 pig上的一种数据组织方式

图3-8 pig上的Map数据组织方式

我们最后看一下来自intellipaat.com的一段简单pig程序:

        Lines=LOAD 'input/Hadoop.log' AS (line: chararray);
        Words = FOREACH Lines GENERATE FLATTEN (TOKENIZE (line)) AS word;
        Groups = GROUP Words BY word;
        Counts = FOREACH Groups GENERATE group, COUNT (Words);
        Results = ORDER Words BY Counts DESC;
        Top5 = LIMIT Results 5;
        STORE Top5 INTO /output/top5words;

就算不作注释,这段代码的可读性也是非常好的。这段代码做的事情就是把Hadoop.log中所有的单词作一个统计,并输出出现频率最高的5个单词。

我们从pig的名字就可以看出,pig程序的开发团队是一个很有趣的团队,而他们设计的Pig latin编程语言也很好地保持了三个特性。

(1)KISS(Keep It Simple Stupid),保持简单的原则。

(2)pig程序很聪明。因为猪是很聪明的动物,所以Pig latin的编译器能够很有效地作好优化,这样程序员们就能够专注于他们自己的主要任务。

(3)pig程序是可扩展的,所以程序员们可以添加特有功能来处理他们自己独特的商业问题。

3.3.3 数据挖掘工具Mahout

在Hadoop上,让统计模型作独立的MapReduce计算不是一件容易的事情,因为:

(1)一般的统计模型计算都是串行的,后面的计算会基于之前的结果;

(2)如果通过创建“线程”来作并行计算,线程之间可能需要数据的共享;

(3)大部分统计学专家并不了解MapReduce模型的细节。

所幸的是,Hadoop上有专门的组件来帮助用户解决这些问题。Mahout就是这样的一个Apache开源项目,它提供了基于Java语言的分布式数据挖掘算法程序库,一些通用的数据挖掘算法都能在其上找到,比如分类算法、聚类算法、协同过滤算法、关联规则分析等。

Mahout对这些算法在Hadoop上运行作了优化,不过它同时也可以在Hadoop环境之外独立运行。

Mahout最终的输出结果可以是JSON和CSV格式,也可以是其他定义的格式。

在Mahout上运行的算法越来越多,不过可能依然不能满足某一个用户的特定需要,而最主要的原因是,把算法移植到Hadoop平台上并不是一件轻松的活儿。这时,可能需要引入另外一个工具:R语言。

3.3.4 专注于数据挖掘的R语言

人们对R语言的描述有很多,通常的定义为:一个能够自由有效地用于统计计算和绘图的语言和环境,又或者是用于统计分析、数据挖掘等各个数据领域的应用软件。在外界对R语言的众多介绍和定义中,笔者比较喜欢Google首席经济学家Hal Varian对它的描述:R语言的美妙之处在于您能用它做各种各样的事情,这归功R上可以免费使用的程序包,所以有了R,您可以真正站在巨人的肩膀上。

R是由统计学家设计的,所以它处处都打上了统计工具的烙印,即为了更好地方便没有计算机编程基础又渴望对数据进行分析挖掘的统计学者,R语言拥有完整体系的数据分析工具,而且为数据分析结果的显示提供了强大的图形功能。

R语言汇集了面向对象语言(Objected Oriented Language)和数学语言的特点。它的基本语法结构主要有以下内容。

(1)标准的和基于各种设备的输入输出;

(2)面向对象编程方式和数学编程方式;

(3)分布式计算结构;

(4)引用程序包;

(5)数学和统计学各种函数,包括基本数学函数、模拟和随机数产生函数、基本统计函数和概率分布函数;

(6)机器语言学习功能;

(7)信号处理功能;

(8)统计学建模和测试功能;

(9)静态和动态的图形展示。

读者可以到R语言的镜像站下载最新版本的R来体验它强大的功能:http://cran.r-project.org/。这里的cran是Comprehensive R Archive Network(R综合典藏网)的英文首字母缩写,它除了收藏了R的执行文件下载版、源代码和说明文件,也收录了各种用户撰写的软件包。到目前为止,全球有超过一百个CRAN镜像站,提供了数千个软件包,而且几乎所有通用的数据挖掘算法都有对应的软件包。

不过,R语言和Hadoop的结合也不是那么容易的。在R语言的早期版本中,要求所有的数据都加载到同一台计算机的内存中才能运行,所以能够处理的数据规模是有限制的。

在过去的几年中,R语言的支持者们一直在努力把R语言和Hadoop结合在一起,这样就能充分利用Hadoop的可扩展性和R语言的数据挖掘能力。RHive、RHadoop、Revolution R以及IBM的BigInsights Big R都是这样的尝试。

3.3.5 数据仓库工具Hive

Hive是蜂巢的意思,而我们这里说的Hive是Hadoop上的数据仓库工具。

Hive的作用就是提供数据整合、查询和分析的功能,它能提供简单的SQL查询功能,可以将SQL语句转换为MapReduce任务进行运行。

Hive系统提供了类似SQL的查询语言HiveQL,其语法和MySQL的语法基本一致,比如下面的命令可以新建一个表:

        CREATE TABLE animals(animal STRING, weight INT, length INT)
        ROW FORMAT DELIMITED
            FIELDS TERMINATED BY '\t';

需要注意的是,这条命令中的ROW FORMAT子句,它是HiveQL定义的,说明数据文件是由制表符“\t”分隔开的文本所构成的。

Hive上的核心部件主要如下。

UI:用户界面,Hive提供命令行界面(Command Line Interface)和图形界面(Graphical User Interface)。

Driver:驾驶部件,这个部件提供JDBC/ODBC的接口。

Compiler:编译器,这个部件解析Query,作语义分析,最终生成执行计划。

Metastore:宏存储,这个部件保存了数据仓库中不同表格和分区的结构信息。

Execution Engine:执行引擎,这个部件负责执行Compiler生成的执行计划,这个计划其实是不同阶段的DAG(有向图)。

Hive的执行流程如图3-9所示。

图3-9 Hive的执行流程

图3-9中Hive的执行流程具体如下。

(1)UI调用Driver上的接口开始作Query(查询)。

(2)Driver为Query创建一个Session Handle(会话手柄),并把Query发送给Compiler(编译器),生成一个执行计划。

(3)Compiler向Metastore(宏存储)请求宏数据。

(4)Metastore返回宏数据给Compiler。

(5)Compiler把生成的执行计划返回给Driver。

(6)Driver把执行计划提交给Execution Engine(执行引擎)。

(7)UI向Driver申请结果。

(8)Driver从Execution Engine获取结果。

(9)Execution Engine从Hadoop系统上获取结果。

前面介绍过,Hadoop上原生的数据库系统HBase是不支持Join操作的,而在Hive系统中,Join操作是可以实现的。

3.3.6 数据采集系统Flume

Flume是Apache旗下的一款高可靠、高扩展、容易管理、支持客户扩展的开源数据采集系统。Flume使用JRuby来构建,所以也依赖Java运行环境。

Flume可以有效地收集、整合大量的数据。对于数据流,Flume用一个很简单灵活的架构来处理,如图3-10所示。

图3-10 Flume数据流向

图3-10中从数据来源(Incoming Data)到数据流出(Outgoing Data),每一个Flume的中间节点都有三个组成部分。

(1)Source,数据源,负责接收数据,并把数据写入管道。

(2)Channel,管道,负责缓存从数据源到下水道的中间数据。

(3)Sink,下水道,负责从管道中获取数据并且分发给下一个接收数据的节点,可能是下一个Flume节点,也可能是最终的目的地。

读者可以到Flume的官网上了解更多的细节:https://flume.apache.org/

对于非结构化的文件,Flume不如Kafka容易处理,所以在本书的案例中,Kafka出现的概率会高一些。