PIG 设计模式(一)
零、前言
这本书是实现大数据分析能力的实用指南。它指导您的大数据技术专家完成准备数据、应用分析和从数据中创造价值的过程。所有这些都是通过在 Pig 中使用适当的设计模式来完成的。我们选择 Pig 来证明它有多有用,这可以从以下几点清楚地看出:
- Pig 通过其简单的语言构造具有内在的可修改性,非常容易学习,其可扩展性和对结构化和非结构化大数据的适用性使其成为首选。
- Pig 可以轻松快速地实现模式,并从任何大数据中明显的随机性中获得意义,这是值得称赞的。
- 本书指导系统架构师和开发人员更熟练地使用 Pig 创建复杂的分析解决方案。它通过让他们接触各种 Pig 设计模式、UDF、工具和最佳实践来做到这一点。
通过阅读这本书,你将实现以下目标:
- 通过跨平台执行数据移动、数据接收、分析、验证、转换、数据缩减和输出,简化创建复杂数据管道的流程;你也可以在这些设计模式中使用 Pig。
- 创建解决方案,使用模式对多结构未建模数据进行探索性分析,从而从中导出结构,并将数据移动到下游系统进行进一步分析。
- 解释 Pig 如何与 Hadoop 生态系统中的其他工具共存,使用设计模式创建大数据解决方案。
这本书包括什么?
第一章在 PIG中设定了设计模式的脉络,为设计模式奠定了基础。Hadoop、MapReduce 及其生态系统组件逐渐暴露了 Pig、其数据流范式以及使 Pig 工作所需的语言结构和带有几个基本示例的概念。它为了解 Pig 最适合的各种工作负载以及 Pig 如何得分提供了背景。如果你有足够的动力去学习更多关于 PIG 的知识,这一章更多的是一个快速实用的参考,并指出更多的参考。
第二章、数据摄取输出模式说明了处理各种数据源的数据摄取输出设计模式。本章包括具体的例子,说明了与外部系统集成的技术,该技术发送多结构和结构化的数据,并使用 Hadoop 作为接收点。本章还讨论了将数据从 Hadoop 导出到外部系统的模式。为了解释这些接收和输出模式,我们考虑了几种文件系统,包括但不限于日志文件、JSON、XML、MongoDB、Cassandra、HBase 等常见的结构化数据源。阅读本章后,您将能够更好地对企业环境中与接收和输出相关的模式进行编程,并且您可以通过使用正确的 Pig 编程或编写自己的 UDF 程序来应用这些知识来构建这些模式。
第三章、数据分析模式重点介绍了适用于各种数据格式的数据分析模式,并在 Pig 中实现了这些模式。这些模式包括 Pig 的不同方法、分析数据和发现数据质量问题的基本和创新统计技术。您将学习如何使用 Pig 在您的企业环境中编程类似的模式,并编写自己的 UDF 来扩展这些模式。
第四章、数据校验与清理模式是关于适用于各种数据格式的数据校验与清理模式。验证模式处理约束、正则表达式和其他统计技术。数据清理模式处理简单过滤器、布隆过滤器和其他统计技术,为应用转换准备数据。
第五章、数据转换模式涉及 Hadoop 中应用于各种数据类型的数据转换模式。阅读本章后,您将能够选择基本转换的正确模式,并了解广泛使用的概念,例如创建连接、汇总、聚合、立方体、汇总数据、泛化和属性构造,必要时使用 Pig 的编程构造和 UDF。
第 6 章了解数据约简模式并解释应用于已被摄取、清理和转换的数据的数据约简模式。阅读本章后,您将能够理解并使用模式进行降维、采样技术、宁滨、聚类和无关属性约简,从而为数据分析做好准备。本章讨论了使用 Pig 语言的各种技术,并扩展了 Pig 的功能,以提供复杂的数据简化用法。
第七章、高级模式及未来工作涉及高级数据分析模式。这些模式涵盖了 Pig 语言的可扩展性,并用案例解释了与可执行代码集成的方法,映射了用 Java 编写的 reduce 代码,来自 PiggyBank 的 UDF 等来源。高级分析涵盖与自然语言处理、聚类、分类和文本索引相关的模式。
这本书的动机
写这本书的灵感来源于我以工作为生,即引领大数据的企业实践,参与基于大数据技术栈的解决方案的创新和交付。
作为这个角色的一部分,我参与了许多用例、解决方案架构的试点以及许多大数据解决方案的开发。根据我的经验,Pig 是一种灵感,对于想要快速测试一个用例并向业务展示价值的用户有很大的吸引力。我用 Pig 证明了快速盈利,解决了需要不太陡峭的学习曲线的问题。同时我发现企业使用 Pig 的书面知识在某些情况下是不存在的,如果有这样的知识会广泛传播。个人认为有必要有一本基于用例模式的知识参考书。通过这本书,我想分享我的经验和教训,并从模式的角度向你传达 Pig 在解决你常见问题方面的可用性和优势。
之所以选择写 Pig 的设计模式,还有一个原因是我对 Pig 语言着迷,它的简单性、通用性和可扩展性。我一直在企业环境中寻找一个可重复的 Pig 食谱模式,这启发我将其记录下来,以便更广泛地使用。我想通过贡献一个 Pig 的模式库来传播我在使用 Pig 时学到的最佳实践。我对在各种用例中使用 Pig 的无形可能性非常感兴趣。通过这本书,我计划进一步扩大它的应用范围,让 Pig 更快乐地工作。
这本书描述了学习 PIG 的实际和实用方面。它为大数据企业中的常见挑战提供了特定的可重用解决方案。它的目标是指导您快速将 Pig 的使用映射到您的问题上下文,并从设计模式的角度设计端到端的大数据系统。
在本书中,设计模式是一组逻辑连接的企业用例,因此它们可以被分解成易于遵循的离散解决方案,并且可以由 Pig 解决。这些设计模式解决了复杂数据管道的创建、进入、退出、转换、迭代处理、合并和海量数据分析等常见的企业问题。
这本书增强了您对特定设计模式的适用性做出更好决策的能力,并使用 Pig 来实现解决方案。
Pig 拉丁语一直是复杂数据管道、数据迭代处理和研究的首选语言。所有这些用例都包括连续的步骤,在这些步骤中,数据被获取、清理、转换并提供给上游系统。成功地创建一个复杂的管道来集成来自不同结构的多个数据平台的倾斜数据,是任何企业利用大数据并通过分析从中创造价值的基石。
这本书使您能够使用这些设计模式来简化 Pig 的使用,以创建复杂的数据管道,从多个数据源获取数据,清理、分析、验证、转换并最终呈现大量数据。
本书使用用 Java 编写的 Pig 和 UDF 的集成提供了深入的解释和代码示例。每一章都包含一组设计模式来提出和解决与企业用例相关的技术挑战。这些章节彼此相对独立,可以以任何顺序完成,因为它们是根据企业中一组常见步骤的特定设计模式设计的。例如,期待解决数据转换问题的读者可以直接访问的第 5 章和数据转换模式,快速开始使用本章提到的代码和说明。这本书建议你使用这些模式来解决你遇到的相同或相似的问题。如果设计模式不适合特定的情况,创建自己的模式。
这本书的目的不是作为一个完整的 Pig 编程指南,而是作为一本参考书,介绍将 Pig 应用于设计模式的思想。它还旨在使您能够创造性地使用设计模式,并使用它们构建有趣的混搭。
这本书你需要什么?
您将需要访问单个机器(虚拟机)或多节点 Hadoop 集群来执行本书中给出的 Pig 脚本。预计将配置运行 Pig 所需的工具。我们已经用 Pig 0.11.0 测试了本书中的示例,强烈建议您安装此版本。
本书中的 UDF 代码是用不同的语言编写的,比如 Java。因此,允许您使用熟悉的开发工具访问机器是明智的,例如 Eclipse。
建议在开发人员的机器上使用 Pig Pen (Eclipse 插件)来开发和调试 Pig 脚本。
The pen can be downloaded from https://issues. Apache. org/jira/secure/attachment/12456988/org。 Apache. Pig. Pen _ 0. 7 .5. Can download.
这本书是给谁的?
这本书是为已经熟悉 Pig 的有经验的开发者写的。他们期望从用例的角度,能够把企业遇到的数据接收、分析、清理、转换、输出问题联系起来。Pig 的这些超级用户会以这本书为参考,了解 Pig 设计模式对于解决他们的问题的意义。
Hadoop 和 Pig 知识对于您更好地掌握 Pig 设计模式的复杂性是强制性的。为了解决这个问题,的第一章和在 PIG 中设置了设计模式的上下文,其中包含了介绍性的概念,并附有简单的例子。建议读者熟悉 Java 和 Python,以便更好地理解在许多章节中用作示例的 UDF。
约定
在这本书里,你会发现许多区分不同种类信息的文本样式。以下是这些风格及其含义的一些例子。
正文中的码字如下:“从这一点开始,我们将调用解包后的 Hadoop 目录HADOOP_HOME
用 Java 编写的 UDF 代码块设置如下:
package com.pigdesignpatterns.myudfs;
public class DeIdentifyUDF extends EvalFunc<String> {
@Override
public String exec(Tuple input){
try {
String plainText = (String)input.get(0);
String encryptKey = (String)input.get(1);
String str="";
str = encrypt(plainText,encryptKey.getBytes());
return str;
}
catch (NullPointerException npe) {
warn(npe.toString(), PigWarning.UDF_WARNING_2);
return null;
} catch (StringIndexOutOfBoundsException npe) {
warn(npe.toString(), PigWarning.UDF_WARNING_3);
return null;
} catch (ClassCastException e) {
warn(e.toString(), PigWarning.UDF_WARNING_4);
return null;
}
PIG 脚本如下所示:
Users = load 'users' as (name, age);
Fltrd = filter Users by
age >= 18 and age <= 25;
Pages = load 'pages' as (user, url);
Jnd = join Fltrd by name, Pages by user;
Grpd = group Jnd by url;
Smmd = foreach Grpd generate group,
COUNT(Jnd) as clicks;
Srtd = order Smmd by clicks desc;
Top5 = limit Srtd 5;
store Top5 into 'top5sites'
任何命令行输入或输出都编写如下:
>tar -zxvf hadoop-1.x.x.tar.gz
新名词和重要词汇以粗体显示。您在屏幕上看到的单词,例如菜单或对话框中的单词,出现在以下文本中:“单击下一步按钮进入下一个屏幕。”
注
否则这样的盒子里会出现一个重要的警告。
型
技巧和技巧是这样出现的。
读者反馈
欢迎读者反馈。让我们知道你对这本书的看法——你喜欢或不喜欢什么。读者的反馈对我们开发标题非常重要,你可以从中真正获得最大的好处。
要给我们发送一般反馈,只需发送电子邮件至<[feedback@packtpub.com](mailto:feedback@packtpub.com)>并通过您消息的主题提及书名即可。
如果您对某个主题有专业知识,并且有兴趣写作或投稿,请参考我们在www.packtpub.com/authors的作者指南。
客户支持
现在,您很自豪拥有一本书,我们有很多东西可以帮助您从购买中获得最大收益。
下载示例代码
你可以下载你在www.packtpub.com账户购买的所有 Packt 书籍的样本代码文件。如果你是在外地买的这本书,可以访问www.packtpub.com/support注册,通过邮件直接把文件发给你。本书中的例子是通过为 Pig 0 . 11 . 0 版本编译来测试的。许多 Pig 脚本、UDF 和数据都可以从发行商的网站或 GitHub 上获得。
也可以使用github.com/pradeep-pas…。
PIG 脚本的例子按照章节组织在各自的目录中。Java 和 Python 的 UDF 也是章节目录的一部分,并被组织在一个名为src的单独子目录中。所有数据集都在数据集目录中。包括自述文件,以帮助您建立 UDF 和理解数据文件的内容。
每个脚本都是在假设输入和输出都在 HDFS 路径上的情况下编写的。
第三方库
为了方便起见,使用了许多第三方库。它们包含在 Maven 依赖项中,因此使用这些库不需要额外的工作。下表列出了在整个代码示例中常用的库:
|库名
|
形容
|
戒指
| | --- | --- | --- | | 数据单元 | 数据单元是用户自定义函数的集合,用于处理 Hadoop 和 Pig 中的大规模数据,尤其是数据挖掘和统计。 | search.maven.org/remoteconte… | | Mungo -hadoop Akin | 这是 Hadoop 的一个插件,它提供了使用 MongoDB 作为输入源和/或输出源的能力。 | http://repo 1 .梅文 org/maven 2/org/MongoDB/Mongo-Hadoop-core _ 1 .0 . 0/1 . 0 . 0-rc0/mongo-Hadoop-core _ 1 .0 .0-1 .0 .0-rc0 .罐子 | | 蒙古-Hadoop-PIG | 这是为了从 MongoDB 数据库中加载记录,以便它们可以在 Pig 脚本中使用并写入 MongoDB 实例。 | http://repo 1 .梅文 org/maven 2/org/MongoDB/Mongo-Hadoop-pig/1 .0 .0/mongo-Hadoop-pig-1 .0 .0 .罐子 | | Mongo-Java-驱动程序 | 这是 MongoDB 的一个 Java 驱动程序。 | http://repo 1。苏慕恩梅文 maven .-什么:1 云娥/2 .9 .0/Java mongo 云娥-2.9.0.jar | | 大象 PIG | 这是 Twitter 的 PIG 装载功能开源库。 | http://repo 1 .梅文 org/maven 2/com/Twitter/象鸟/象鸟-PIG/3 .0 .5/象鸟-PIG-3.0.5.jar | | 鸟芯 | 这是推特核心实用程序的集合。 | http://repo 1 .梅文 org/maven 2/com/Twitter/象鸟/象鸟-PIG/3 .0 .5/象鸟-PIG-3.0.5.jar | | hctalog-清管器适配器 | 它包含从 Hcatalog 管理的表中访问数据的实用程序。 | search.maven.org/remoteconte… | | cb2java | 这个罐子优酷动态解析 cobol 字帖。 | http://SourceForge .net/project/cb2 Java/file/latest/下载 | | 罗欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧欧 | 这是 Avro 核心组件库。 | http://repo 1 .梅文 org/maven 2/org/Apache/4 月/4 月/1 .7 .4/4 月-1.7.4.jar | | json-simple | 这个库是一个用于 JSON 编码或解码 JSON 文本的 Java 工具包。 | http://www .java2s .com/Code/JarDownload/JSON-simple/JSON-simple-1 .1 .1 .罐子。拉链 | | 公地数学 | 这个库包含很少的数学和统计成分。 | http://repo 1。苏慕恩梅文 maven .文士/maven 2/org/Apache/commons/commons-math 3/3.2/commons-math 3-3.2。jar〔t1〕t1〔t1〕 |
数据集
在本书中,您将使用这些数据集为示例提供一些多样性。可以在 github.com/pradeep-pas… 目录的 GitHub 存储库中获得所用确切数据的副本。只要相关,章节特定数据就存在于相同 GitHub 位置下的章节特定子目录中。
以下是数据集的主要分类,它们与本书中讨论的用例相关:
-
The logs dataset contains a month's worth of HTTP requests to the NASA Kennedy Space Center WWW server in Florida. These logs are in the format of Apache access logs.
注
数据集从链接ftp://ita.ee.lbl.gov/traces/NASA_access_log_Jul95.gz和ftp://ita.ee.lbl.gov/traces/NASA_access_log_Aug95.gz下载。
鸣谢:日志由肯尼迪航天中心的吉姆·杜穆林收集,萨斯喀彻温大学的马丁·朴正洙(
<[mfa126@cs.usask.ca](mailto:mfa126@cs.usask.ca)>)和凯里·威廉姆森(<[carey@cs.usask.ca](mailto:carey@cs.usask.ca)>)提供。 -
自定义日志数据集包含由 web 应用以自定义日志格式生成的日志。事件日志中嵌入了 Web 服务请求和响应信息。这是一个专门为说明本书中的例子而创建的复合数据集。
-
The historical NASDAQ stock data from 1970 to 2010, including daily open, close, low, high, and trading volume figures. Data is organized alphabetically by ticker symbol.
注
本数据集下载自链接 http://www .信息黑猩猩. com/dataset/Nasdaq-exchange-daily-1970-2010-开盘-收盘-高-低-成交量/下载量/166853 。
-
客户零售交易数据集包含购买产品类别的详细信息和客户人口统计信息。这是一个专门为说明本书中的例子而创建的复合数据集。
-
汽车保险索赔数据集由两个文件组成。
automobile_policy_master.csv单据中包含车辆的价格和为此支付的保费。文件automobile_insurance_claims.csv包含了汽车保险的理赔数据,具体是车辆修理费的理赔。这是一个专门为说明本书中的例子而创建的复合数据集。 -
The MedlinePlus health topic XML files contain records of health topics. Each health topic record includes data elements associated with that topic.
注
该数据集可从链接 http://www .健康数据. gov/data/dataset/medlineplus-health-topic-XML-files-0下载。
-
This dataset contains a large set of e-mail messages from the Enron corpus which has about 150 users with an average of 757 messages per user; the dataset is in AVRO format and we have converted it to JSON format for the purpose of this book.
注
本数据集下载自链接 S3 .亚马逊 com/rjurney _ public _ web/Hadoop/Enron .avro 。
-
电器制造数据集是为了本书的目的而创建的复合数据集。此数据集包含以下文件:
manufacturing_units.csv:包含每个制造单元的信息。products.csv:包含产品的详细信息。manufacturing_units_products.csv:保存不同制造单位生产的产品的详细信息。production.csv:这里保存生产明细。
-
非结构化文本数据集包含一些来自维基百科的关于计算机科学和信息技术、大数据、医学、电话发明、停用词列表和词典词表的文章。
-
Outlook 联系人数据集是一个复合数据集,它是出于本书的目的通过导出 Outlook 联系人而创建的;它是一个带有属性联系人名称和标题的 CSV 文件。
-
The German credit dataset in CSV format classifies people as good or bad credit risks based on a set of attributes. There are 20 attributes (7 numerical and 13 categorical) with 1,000 instances.
注
数据集可从链接archive.ics.uci.edu/ml/machine … 下载。
鸣谢:数据来自 UCI 机器学习知识库(http://archive . ics . UCI . edu/ml/datasets/stat og+(德语+Credit+Data)),来源:汉堡大学统计与经济研究所教授汉斯·霍夫曼博士。
勘误表
虽然我们尽最大努力确保内容的准确性,但错误还是会发生。如果你在我们的一本书里发现一个错误——可能是文本或代码中的错误——如果你能向我们报告,我们将不胜感激。通过这样做,你可以让其他读者免受挫折,并帮助我们改进这本书的后续版本。如有勘误,请访问www.packtpub.com/support,选择您的图书,点击勘误T4【提交 表格链接,输入您的勘误详情。一旦您的勘误表得到验证,您的提交将被接受,勘误表将被上传到我们的网站或添加到标题勘误表部分下的任何现有勘误表列表中。
盗版
互联网上版权材料的盗版是所有媒体的一个老大难问题。在 Packt,我们非常重视版权和许可证的保护。如果您在互联网上遇到任何形式的非法复制我们的作品,请立即向我们提供位置地址或网站名称,以便我们寻求补救措施。
请联系我们<[copyright@packtpub.com](mailto:copyright@packtpub.com)>获取疑似盗版资料的链接。
我们感谢您在保护我们的作者方面的帮助,以及我们为您带来有价值内容的能力。
问题
如果您对本书有任何疑问,可以在<[questions@packtpub.com](mailto:questions@packtpub.com)>联系我们,我们会尽力解决。
一、为 PIG 的设计模式设定背景
本章旨在对本书涉及的各种技术和概念提供一个宽泛的介绍。我们从探索与设计模式相关的概念开始,通过定义它们并理解它们是如何在现实生活中被发现和应用的,我们寻求理解这些设计模式是如何在 Pig 中被应用和实现的。
在开始研究 Pig 编程语言的复杂性之前,首先要探究 Pig 产生的背景、Pig 在企业中的使用地位以及 Hadoop 如何适应大数据时代的分布式计算环境。然后,我们快速进入 Hadoop 生态系统,向大家介绍它的重要功能。已经从语言特性的角度介绍了 Pig 编程语言,为大家提供了一个现成的例子,详细讲解了语言特性,比如常用运算符、可扩展性、输入输出运算符、关系运算符、模式、空值以及理解中间 MapReduce 代码的方法。
了解设计模式
设计模式为类似的问题或需求提供一致且通用的解决方案。在处理不同的系统时,设计者往往会遇到问题本身的相似性或者需要满足的需求。最终,他/她获得了足够的关于细微变化的知识,并开始看到连接这些不同且反复出现的问题的共同线索。这些共同的行为或特征然后被抽象成一个模式。因此,这种模式或解决方法是一种通用设计,也可以应用于更广泛的需求集和新形式的问题。比如广受好评的《软件设计模式》由Erich GammaRichard HelmRalph JohnsonJohn VlisidesAddison-Wesley Professional编写的《设计模式:可重用面向对象软件的要素》一书,这些模式也可以通过分析现实生活中追溯到非软件领域的情况来理解。本书中提到的工厂方法模式定义了一个创建类对象的接口,但是它让子类决定实例化哪个类。这种软件模式在非软件行业似乎有相似之处,玩具都是通过注塑成型的。该机器加工塑料粉末,并将粉末注射到所需形状的模具中。玩具的类型(汽车、动作人物等)。)是由他们的模具决定的。
设计模式不是为了解决一个特定的问题,这个问题可以像一个完美的定制解决方案一样转换成代码。相反,它就像一个模板,用来解决特定的、定义明确的问题。通常,设计模式是在现实生活中发现的;他们不是被创造出来的。以下是发现模式的一般方法:
- 共同解决最新问题的一组新技术的演变;这些技术认为需要一个模式目录。
- 反复出现的问题的解决方案
使现有模型适应新的情况,并修改现有模型本身。找到一个模式意味着定义它,给它一个名字,并以一种非常清晰的方式记录下来,以便用户在面临类似问题时能够阅读、理解和应用它们。当一个模式被真实用户使用,并且他们已经解决了现实世界的问题而不是假设的问题时,它是值得发布的。这些模式不是规则或法律;它们是指导原则,可以根据解决方案的需要进行修改。
这本书的灵感来自其他不同主题领域的设计模式书籍。它也遵循 GoF 模式目录设计模式:可重用的面向对象软件元素、由 Gamma 、 Helm 、*Johnson&Foley Sieders(Addison-Wesley 专业版)*勾勒的模式文档格式。
本书中的每个设计模式都遵循一个模板,并由一个名称标识,后面是几个部分,告诉用户更多关于模式的信息。
- 名称模式提供了一个唯一的标识符,这是一种很好的交流方式。
- 模式的细节部分简要描述了模式的内容和原因。
- 背景描述模型的动机和详细适用性。
- 动机描述一个具体的场景,描述问题以及模式如何适合作为解决方案。适用性描述了使用模式的不同情况。
- 用例处理真实系统中的各种用例,在这些用例中我们可以看到模式的证据。
- 代码片段的部分由实现该模式的代码组成。
- 结果包含模式的结果,处理模式输出的预期和意外效果。
- 附加信息部分加工模式相互关联,以及与模式相关的任何其他相关信息。
当您识别出一个问题时,您应用了一个模式,一个模式可以解决这个问题,并识别与其他问题的相似性,这些问题可以通过使用已知的模式来解决。这可能发生在初始设计、编码或维护阶段。要做到这一点,你需要熟悉现有的模式及其关系,然后看背景部分,深入研究模式设计问题的动机和适用性。
PIG 的设计模式范围
本书讨论了在企业环境中解决现实世界中反复出现的大数据问题时遇到的模式。对这些模式的需求根植于 Pig 的发展,以解决大量数据的新兴问题,以及对模式目录的感知需求来记录他们的解决方案。
在处理大量数据时遇到的问题通常涉及到牢牢把握数据是否可以用来生成分析意见,如果可以,如何高效地生成这些意见。把自己想象成一个数据科学家,他得到了大量的数据,这些数据没有合适的模式,无序,长时间没有被记录。要求您将其与其他企业数据源集成,并生成引人注目的分析见解。你怎么开始?你会开始整合数据,开始你最喜欢的分析沙盒,并开始产生结果吗?如果你提前知道设计模式的存在,并且在这种情况下可以系统有序的应用这些模式,以减少错误,提高大数据分析的效率,你会觉得方便吗?在这种情况下,本书讨论的设计模式肯定会吸引你。
Pig 中的设计模式旨在提高你处理大数据问题的能力,快速应用模式解决问题。使用 Pig 成功开发大数据解决方案需要在开发生命周期的早期阶段考虑问题,这些模式有助于发现这些问题。重用 Pig 设计模式可以帮助识别和解决这些微妙之处,并防止它们发展成主要问题。模式应用的副产品是最终代码的可读性和可维护性。这些模式为开发人员提供了一个有价值的交流工具,允许他们使用一个通用的词汇表来讨论模式可以解决的问题,而不是用冗长的方式解释问题的内部。PIG 的设计模式不是成功的食谱;它们是经验法则。阅读本书中关于 Pig 设计模式的具体案例,可能有助于你尽早发现问题,从而避免未来指数级的返工成本。
设计模式的流行很大程度上取决于领域。比如四人帮书中的状态模式、代理、外观,在与其他系统进行通信的应用中非常常见。同样,使用大数据来理解分析意见的企业使用与解决数据管道问题相关的模式,因为这是一个非常常见的用例。这些模式具体描述了 Pig 在数据接收、分析、清理、转换、还原、分析和输出中的应用。
第 5 章讨论的几种模式数据转换模式第 6 章了解数据约简模式,使已有模式适应新情况,并在过程中对已有模式本身进行修改。这些模式处理 Pig 在增量数据集成和快速原型开发中的使用。
这些设计模式也更深入,使您能够确定 Pig 的特定语言结构对给定问题的适用性。以下问题更好地说明了这一点:
- 解决特定模式投影的推荐用法是什么?
- 标量投影在哪种模式下最适合访问聚合?
- 哪些模式不建议使用
COUNT、SUM、COUNT_STAR? - 在关键点分布不均的格局中,如何有效利用排序?
- 哪些模式与溢出数据类型的正确使用有关?
- 当不使用多个
FLATTENS操作符时,会导致CROSS出现在袋子上? - 有哪些模式描述了嵌套
FOREACH方法的理想用法? - 当一个数据集可以存入内存时,
JOIN操作选择哪些模式? - 当一个键在连接关系中占主导地位时,
JOIN操作应该选择哪种模式? - 两个数据集排序后,
JOIN操作选择哪些模式?
Hadoop 揭开神秘面 Yarn——一个快速计算器
现在,我们将讨论处理巨大的多结构数据的需求,以及用传统的分布式应用处理如此巨大的数据所涉及的挑战。我们还将讨论 Hadoop 的出现以及它如何有效地应对这些挑战。
企业背景
过去的十年是数据史上的决定性时刻,引领企业采用新的商业模式,利用大规模数据增长带来的机遇。
互联网搜索、个性化音乐、平板电脑、智能手机、3G 网络和社交媒体的激增,推动了数据管理规则的变化,从数据的组织、获取、存储和检索的角度转向管理。需要对这些新的数据源进行决策并获得有价值的见解,这已经成为企业武库中的一件有价值的武器,旨在企业取得成功。
基于关系数据库管理系统的数据仓库等传统系统率先支持决策过程,可以应用传统的统计度量方法对数据进行收集、存储和管理,从而创建了一个报告和分析平台。这些传统系统收集的数据本质上是高度结构化的,随着新兴数据类型的需求而变化的灵活性极低,而新兴数据类型的非结构化程度更高。
这些数据仓库可以支持分布式处理应用,但是有很多限制。这种分布式处理应用通常面向获取结构化数据,对其进行转换并使其可用于分析或报告,这些应用主要是批处理作业。在某些情况下,这些应用运行在机器集群上,将计算和数据分发到集群的节点。这些应用获取大量数据,对其执行计算密集型操作,并将其发送到下游系统,供另一个应用或系统使用。
随着对结构化和非结构化数据分析和洞察的竞争需求,当前企业需要处理前所未有的海量数据。该处理主要涉及执行清理、分析和转换非结构化数据和企业数据源所需的操作,以便结果可用于获得有用的分析见解。处理这些大型数据集需要许多中央处理单元、足够的输入/输出带宽、内存等。另外,每当有大规模的治疗,就意味着我们要应对各种失败。传统的系统,如关系数据库管理系统,在如此巨大的数据负载下或数据变化不可预测的情况下,无法进行线性或经济高效的扩展。
为了应对数据的异常涌入,显然需要数据管理技术解决方案;这使我们能够在短时间内以不同的复杂程度消费多种格式的大量数据,从而创建一个强大的分析平台来支持决策。
分布式系统的常见挑战
在 Hadoop 出现之前,分布式应用试图应对数据增长和并行处理的挑战,其中处理器、网络和存储故障屡见不鲜。分布式系统通常必须管理生态系统中每个组件的故障,这些故障是由磁盘空间不足、数据损坏、性能下降、路由问题和网络拥塞引起的。在传统架构中几乎不可能实现线性可扩展性,在有限的可能性下也不是没有很大的成本。
高可用性是以牺牲可扩展性或完整性为代价实现的。缺乏对并发性、容错性和数据可用性的良好支持,不利于处理大数据的传统系统的复杂性。此外,如果我们要部署一个包含最新预测算法的定制应用,分布式代码有其自身的同步、锁定、资源争用、并发控制和事务恢复等问题。
在关系数据库管理系统的传统数据仓库系统中,以前讨论的分布式计算问题很少以多种方式处理,但这些解决方案不能直接扩展到大数据的情况。在这种情况下,由于数据量巨大及其多样性和速度,问题将呈指数级放大。数量问题在一定程度上是可以解决的。然而,数据多样性和数据速度的问题非常昂贵,并且不能通过这些控制传统系统来解决大数据问题的尝试来解决。
随着时间的推移,问题越来越大,处理大数据的解决方案被分布式处理、分布式存储、人工智能、多处理器系统、面向对象概念和互联网数据处理技术等多种技术的智能结合所接受。
Hadoop 的出现
Hadoop 是一个可以容忍机器故障的框架。它是为了克服前面讨论的分布式系统的挑战而构建的。Hadoop 提供了一种使用机器集群并行存储和处理海量数据的方法。它是一种基于文件系统的可扩展分布式数据处理架构,设计并部署在高吞吐量和可扩展的基础设施上。
Hadoop 起源于 Google,Google 创造了一种新的计算模型,基于文件系统 Google 文件系统 ( GFS ) 和编程框架 MapReduce,扩展了搜索引擎的规模,可以同时处理多个查询。 Doug Cutting 和 Mike Cafarella 改编了谷歌的这个计算模型,重新设计了他们名为 Nutch 的搜索引擎。这最终导致了 Nutch 作为开源下的顶级 Apache 项目的发展,2006 年被雅虎采用,最终转化为 Hadoop。
以下是 Hadoop 的主要特性:
- Hadoop 给大众带来了尴尬的大规模并行处理能力。
- 通过使用文件系统存储,Hadoop 将对数据库的依赖降至最低。
- Hadoop 使用定制的分布式基于文件的存储,这比存储在存储昂贵的数据库中要便宜,例如存储区域网络 ( 存储区域网络 ) 或其他专有存储解决方案。因为数据以文件的形式分布在集群中的机器上,所以它使用多节点复制来提供内置冗余。
- Hadoop 的核心原则是使用商品基础设施,这是线性可扩展的,以适应无限的数据,而不会降低性能。这意味着每增加一个基础设施,无论是 CPU、内存还是存储,都会带来 100%的可扩展性。这使得使用 Hadoop 的数据存储成本低于传统的数据存储和处理方法。从不同的角度来看,您可以免费完成添加到群集的每 TB 存储空间的处理。
- Hadoop 通过可编程应用编程接口 ( API ) 访问,实现并行处理,不受并发限制。出于不同的目的,相同的数据可以跨系统处理,或者相同的代码可以跨不同的系统处理。
- 利用高速同步在集群的多个节点上复制数据,实现了 Hadoop 的容错操作。
- Hadoop 旨在集成高可用性的关键方面,以便用户始终可以使用和访问数据和基础架构。
- Hadoop 将代码传递给数据,而不是相反;这被称为数据局部性优化。数据的本地处理和结果在同一个集群节点上的存储可以最大限度地减少网络负载,从而提高整体效率。
- 为了设计容错应用,添加容错部件所涉及的工作有时会超过解决手头实际数据问题所涉及的工作。这就是 Hadoop 得分高的地方。通过将分布式系统的容错与应用逻辑分离开来,它使应用开发人员能够不用担心编写应用。借助 Hadoop,开发人员不再需要处理低级挑战,如故障处理、资源管理、并发性、数据加载、集群中每个节点上作业的分配和管理。他们只能专注于创建在集群上工作的应用,让框架来应对挑战。
封面下的 Hadoop
Hadoop 由 Hadoop 核心和 Hadoop 子项目组成。Hadoop 的核心本质上是 MapReduce 处理框架和 HDFS 存储系统。
Hadoop 的组件如下图所示:
典型的 Hadoop 堆栈
以下是 Hadoop 整体部分的描述:
- Hadoop 通用:这个包括所有支持生态系统的库组件和实用程序。
- Hadoop 分布式文件系统(HDFS) :这个是一个文件系统,提供高可用性冗余分布式数据访问,用 MapReduce 进行处理。
- Hadoop MapReduce :这个是一个基于 Java 的软件框架,可以对存储数据的节点集群中的大数据集(HDFS)进行操作。
很少有与 Hadoop 相关的顶级 Apache 项目包括以下系统:
- AVRO :这是一个数据序列化和反序列化系统。
- 楚科瓦:这里是一个日志数据采集系统。
- SQOOP :这个是一个与 RDBMS 集成的结构化数据采集框架。
- hbase :这个是一个面向列的可扩展分布式数据库,支持数百万行和数百万列使用 HDFS 存储和查询实时结构化数据。
- Hive:这个是一个结构化的数据存储和一个基于 HDFS 的查询基础设施,主要用于数据的聚合、汇总和查询。
- 看象人:这个是专门为在分布式集群上执行而编写的机器学习算法库。
- Pig :这个是一个数据流语言,是专门为了简化 MapReduce 应用的编写而设计的。
- 城市动物园:这个是一个为分布式应用设计的协调服务。
了解 Hadoop 分布式文件系统
Hadoop 分布式文件系统 ( HDFS )是一个文件系统,使用 MapReduce 为进程提供高可用性冗余数据访问。HDFS 解决了大规模数据存储和处理中的两个主要问题。第一个问题是数据局部性,其中代码实际上是发送到数据在集群中的位置,其中数据已经被分成可管理的块,以便每个块可以被独立处理,并且结果被组合。第二个问题与任何子系统级别(可以是 CPU、网络、存储、内存或应用级别)的容错能力有关,这是由于对商品硬件的依赖,除非另有证明,否则对商品硬件的依赖较小。为了解决这些问题,HDFS 的建筑受到了 GFS 早期领导人的启发。
HDFS 的设计目标
HDFS 建筑的三个主要目标如下:
- 处理从几千兆字节到几千兆字节的非常大的文件。
- 流数据处理,以高吞吐率读取数据,并在读取时处理数据。
- 它可以在没有特殊硬件要求的商用硬件上执行。
HDFS 的作品
HDFS 有两个重要的子系统。一个是名称节点,它是系统维护和管理其他节点中存在的块的主节点。第二个是数据节点,是在名字节点的监督下工作的从节点,部署在每台机器上提供实际存储。这些节点一起为客户端提供读写请求,客户端从这些节点存储和检索数据。如下图所示:
作业跟踪器和名称节点
主节点是数据拆分的元数据存储在内存中的地方。该元数据用于在稍后的时间点重建从节点中存储的完整数据,以便作业可以在各个节点上运行。至少在三台机器上复制数据分割(默认复制因子)。当从节点的硬件出现故障时,这很有帮助,并且可以从存储冗余副本的机器上恢复数据,并且在其中一台机器上执行作业。他们共同负责整个集群中数据的存储、复制和管理。
在 Hadoop 集群中,文件系统节点(数据节点)中的数据被复制到集群中的多个节点。这种复制增加了系统在机器或子系统故障时的冗余度;存储在其他机器中的数据将用于继续处理步骤。因为数据和处理在同一个节点上共存,所以只有增加一台新机,并获得额外硬盘驱动器的好处和新 CPU 的计算能力(横向扩展),才能实现线性可扩展性。
应该注意的是,HDFS 不适合低延迟数据访问,也不适合存储许多小文件、多次写入和任意文件修改。
理解 MapReduce
MapReduce 是一个操纵和处理庞大数据集的编程模型;它的起源可以追溯到谷歌,谷歌创建它是为了解决搜索计算的可扩展性。它基于并行和分布式处理的原理,不依赖任何数据库。MapReduce 的灵活性在于它能够处理商品服务器集群中大量数据的分布式计算。Hadoop 和 MapReduce 提供了一个称为数据局部性的工具和一个简单的基于任务的流程管理模型。
了解 MapReduce 的工作原理
MapReduce 主要使用两个组件;一个作业跟踪器,它是一个主守护进程,一个任务跟踪器,它运行在所有从节点中。它是一个从守护进程。如下图所示:
MapReduce 内部
开发人员使用 MapReduce 框架用 Java 编写一个作业并提交给集群的主节点,主节点负责处理作业的所有底层数据。
主节点由一个名为JobTracker 的守护进程组成,该守护进程向从节点分发作业。JobTracker类负责将包含任务的 JAR 文件复制到包含任务跟踪器的节点,这样每个从节点就可以生成一个新的 JVM 来运行任务。将 JAR 复制到从节点将有助于处理从节点的故障。节点故障将导致主节点将任务分配给包含相同 JAR 文件的另一个从节点。这可以在节点故障的情况下保持灵活性。
MapReduce 内部构件
一个 MapReduce 作业有两个功能:
- 映射函数:A 用户编写一个映射函数,接收键值对作为输入,进行处理,发出键值对列表。
- Reduce 函数 : 用户编写的 Reduce 函数将接受 Map 函数的输出,即中间键值对的列表。这些值通常被组合成一组较小的值,因此它们被命名为“减少”。每个 reducer 调用的输出可能只有 0 或 1 个输出值。
以下是上图中描述的 MapReduce 框架的其他组件:
- 合并器:这是优化步骤,可以任意调用。这是一个被指定在映射器端执行类似缩减处理并在中间数据上执行映射器端聚合的功能。这将减少通过网络从映射器传输到缩减器的数据量。
- 拆分器:这个是用来拆分地图输出的键。该键用于通过将一个键的所有值组合在一个分区中来开发一个分区。有时默认分区可以由散列函数创建。
- 输出:这个收集映射器和减速器的输出。
- 作业配置:这是管理 MapReduce 作业的主用户界面,用于指定 Map、Reduce 函数和输入文件。
- 作业输入:这个指定了一个 MapReduce 作业的输入。
PIG-快速入门
由 PIG MapReduce 简化。它是 Pig 编译器和 Pig 拉丁脚本的组合,后者是一种编程语言,旨在简化用于分析大量数据的分布式应用的开发。我们称整个实体为 PIG。
用 PIG 拉丁脚本编写的高级语言代码编译成 MapReduce Java 代码序列,可以并行化。Pig Latin 推动数据成为任何用它编写的程序背后的主要概念。基于数据流范式,它对要处理的数据流起作用;这些数据由指令传输,指令处理数据。这种编程风格类似于电信号如何流经电路或水流过管道。
这种数据流范式与控制流语言形成鲜明对比,控制流语言处理指令流并操作外部数据。在传统程序中,条件执行、跳转和过程调用会改变要执行的指令流。
Pig 拉丁语中的 Processing 语句由接受输入和输出的运算符组成。输入输出是由包、映射、元组和标量数据表示的结构化数据。Pig 类似于数据流图,其中有向顶点是数据路径,节点是处理数据的运算符(如 FILTER、GROUP 和 JOIN)。在 PIG 拉丁语中,每个语句在所有数据到达后立即执行,这与遇到语句后立即执行的传统程序形成对比。
程序员用一套标准的数据处理 Pig 算子 T7 写代码,比如 T8、T0、T1、T9、T2、T3、T10、T4、T5、T11、T6。然后将这些转换为 MapReduce 作业。PIG 本身不具备运行这些工作的能力。它将这些工作委托给 Hadoop。Hadoop 充当这些 MapReduce 作业的执行引擎。
必须明白,Pig 并不是一种通用的编程语言,它自带所有花哨的功能。例如,它没有控制流或范围分辨率的概念,并且具有最小的变量支持,这是许多开发人员在传统语言中习惯的。使用自定义函数(【UDFS】)可以克服这个限制,这是 Pig 的一个可扩展特性。
为了更深入地了解,您可能需要参考 pig.apache.org/docs/r0.11.… Apache 网站来了解复杂的语法、用法和其他语言功能。
了解 PIG 的基本原理。
Pig Latin 设计为数据流语言,解决 MapReduce 的以下局限性:
- MapReduce 编程模型具有紧密耦合的计算,可分为映射阶段、洗牌阶段和约简阶段。这种限制不适用于不适合这种模式的实际应用和具有不同进程的任务(如连接或 N 相)。很少有其他真实世界的数据管道需要额外的协调代码来组合单独的 MapReduce 阶段,以管理管道阶段之间的中间结果。就新开发人员理解计算的学习曲线而言,这是有代价的。
- 即使是最简单的操作,如投影、过滤和连接,也必须在 MapReduce 中实现复杂的变通方法。
- MapReduce 代码很难开发、维护和重用,有时比 Pig 中编写的相应代码复杂得多。
- 由于实现的复杂性,在 MapReduce 中很难进行优化。
PIG 拉丁带来双重优势。它是一种类似 SQL 的语言,具有声明性风格和过程编程语言的能力(例如具有各种可伸缩性特征的 MapReduce)。
Pig 支持嵌套数据和将复杂数据类型作为表的字段嵌入。嵌套数据模型的支持使数据建模更加直观,因为它比数据库以第一范式建模数据的方式更接近数据存在的真实情况。嵌套数据模型还反映了数据在磁盘上的存储方式,使用户能够更直观地编写自定义 UDF。
Pig 支持创建自定义功能,执行特殊数据处理任务;小 PIG 编程的几乎所有方面都可以被 UDF 扩展。这意味着程序员可以使用EvalFunc方法自定义 Pig 拉丁函数,如分组、过滤和连接。您也可以通过扩展LoadFunc或StoreFunc自定义加载/存储功能。第二章、数据接收输出模式用实例展示了 Pig 的可扩展性。
Pig 有一个特别的功能,叫做ILLUSTRATE功能,帮助大数据开发人员利用样本数据快速开发代码。样本数据尽可能接近真实数据,充分说明了程序的语义。样本数据随着程序复杂度的增加而自动发展。该系统的样本数据有助于早期发现错误及其来源。
使用 Pig 的另一个优点是不需要像传统的数据库管理系统那样在将数据解析成元组之前执行复杂的数据导入过程。这意味着,如果您有一个数据文件,PIG 拉丁查询可以直接在其上运行,而无需导入它。不导入意味着数据只要能被 Pig 读取为元组,就可以任何格式访问和查询。我们不需要像处理数据库一样导入数据,例如,在查询之前将 CSV 文件导入数据库。但是,您需要提供一个函数来将文件内容解析为元组。
了解 PIG 在企业中的相关性
在当前的企业中,大数据处理周期因其复杂性而备受关注,与传统的数据处理周期有很大不同。从各种数据源收集的数据被加载到目标平台;然后,执行基本级别分析,通过应用于数据的元数据层进行发现。这将导致为内容创建数据结构或模式,以便发现数据的上下文和相关性。一旦应用了数据结构,数据将被集成、转换、聚合并准备好进行分析。这个精简的结构化数据集用于报告和特别分析。该过程的结果是提供对数据和任何相关上下文的洞察(基于处理的业务规则)。Hadoop 在每个阶段都可以作为一个处理和存储框架。
下图显示了典型的大数据处理流程:
企业中的大数据
根据上图,PIG 的作用如下:
- 在采集阶段中,Pig 用于对接多种来源采集的数据,包括实时系统、近实时系统和面向批量的应用。使用 Pig 的另一种方式是通过知识发现平台处理数据,知识发现平台可以是上游,存储输出的子集,而不是整个数据集。
- 数据发现阶段使用 Pig,Pig 首先分析大数据,然后进行处理。正是在这个阶段,大数据已经准备好与结构化分析平台或数据仓库集成。发现和分析阶段包括数据的标记、分类和归类,这与主题领域非常相似,并导致数据模型的定义或元数据的创建。这些元数据是通过分析和洞察解读大数据最终价值的关键。
- Pig 用于的数据处理阶段,在此阶段对数据的上下文进行处理探索非结构化环境下数据的相关性;这种关联将有助于在大数据中应用适当的元数据和主数据。这种处理的最大优点是,它可以在多个上下文中处理相同的数据,然后在每个结果集中找到模式,用于进一步的数据挖掘和数据探索。比如考虑到“冷”这个词,就要根据用法、语义等相关信息,正确确定这个词的语境。这个词可能与天气或一种常见疾病有关。在获得这个单词的正确上下文后,可以对数据应用与天气或常见疾病相关的进一步的主数据。
- 在处理阶段,通过用元数据、主数据和语义库对大数据进行清理和标准化,Pig 还可以在数据文化之后立即进行数据集成。这是数据链接到企业数据集的地方。有许多技术可以将结构化和非结构化数据集之间的数据与元数据和主数据联系起来。这个过程是将非结构化和原始数据转换和集成为结构化格式的第一个重要步骤。现阶段,Pig 的力量广泛应用于数据转换,通过从昂贵的企业数据仓库中卸载大量低价值的数据和工作负载来扩展现有的企业数据仓库。
- 由于企业中的处理阶段受到严格的服务级别协议的约束,Pig 的可预测性更强,可以与其他系统集成,因此更适合定期安排数据清理、转换和报告工作负载。
当输入数据没有被清理和规范化时,Pig 得分。它可以很好地处理运行时数据模式未知或不一致的情况。Pig 的过程语言模型和非模态方法在数据访问方面提供了更大的灵活性和效率,因此数据科学家可以在原始数据上构建研究模型来快速测试理论。
Pig 通常用于解决解可以表示为有向无环图 ( Dag )的问题,包括标准关系运算(连接、聚合等)的组合。)的 Pig,并使用定制的处理代码通过 UDF 用 Java 或脚本语言编写。这意味着,如果你有一个非常复杂的任务链,其中每个作业的输出被用作下一个作业的输入,Pig 使链接作业的过程很容易完成。
Pig 在大数据工作负载中非常有用,其中有一个非常大的数据集,这个数据集的处理包括不断添加新的小数据片,这会改变大数据集的状态。Pig 善于结合新到达的数据,所以不会对整个数据进行处理,只会对数据的增量和大数据的结果进行有效处理。Pig 为操作员提供了在合理时间内执行增量数据处理的能力。
除了上面提到的传统用例之外,Pig 还有一个固有的优势,那就是编写和优化代码的开发时间比用 Java MapReduce 编写要少得多。手动优化繁琐时 Pig 是更好的选择。Pig 的可扩展性,通过它可以集成你现有的可执行文件、UDF 和 Pig 拉丁脚本,实现更快的开发周期。
PIG 的工作-概述
本节是一个分析和解释 PIG 的文字来说明 PIG 的语言特征的例子。
点亮 PIG
本部分帮助您快速了解如何通过安装和配置引导 Pig 进入动作模式。
Pig 在 Hadoop 集群中工作的首要前提是保持 Hadoop 版本的兼容性,本质上就是 Pig 0.11.0 和 Hadoop 版本 0.20.X 协同工作。x,0.23.X 和 2.x .这是通过改变 HADOOP_HOME 的目录来实现的。下表显示了 Apache Pig 和 Hadoop 之间的版本兼容性。
下表总结了 PIG 与 Hadoop 的兼容性:
|ApachePIG 版
|
兼容 Hadoop 版本的
| | --- | --- | | 0.12.0 | 0.20.x,1.x,0.23.x,2.x | | 0.11.0 | 0.20.x,1.x,0.23.x,2.x | | 0.10.1 | 0.20.x,1.x,0.23.x,2.x | | 0.10.0 | 0.20、1.0、0.23 | | 0.9.2 | 0.20, 1.0.0 | | 0.9.1 | zero point two | | 0.9.0 | zero point two | | 0.8.1 | zero point two | | 0.8.0 | zero point two | | 0.7.0 | zero point two | | 0.6.0 | zero point two | | 0.5.0 | zero point two | | 0.4.0 | Zero point eight | | 0.3.0 | Zero point eight | | 0.2.0 | Zero point eight | | 0.1.1 | Zero point eight | | 0.1.0 | Zero point seven |
Pigcore 是用 Java 编写的,跨操作系统工作。执行用户命令的 Pig 的外壳是一个 bash 脚本,需要一个 UNIX 系统。Pig 也可以使用 Cygwin 和 Perl 包在 Windows 上运行。
Java 1.6 也是必须输给 Pig 才能操作。或者,您可以在同一台机器上安装以下内容:Python 2.5、JavaScript 1.7、Ant 1.7 和 JUnit 4.5。Python 和 JavaScript 用于编写定制的 UDF。Ant 和 JUnit 分别用于构建和单元测试。通过将 HADOOP_HOME 设置为指向我们已经安装了 HADOOP 的目录,可以用不同版本的 HADOOP 执行 Pig。如果没有设置 HADOOP_HOME,Pig 默认会在嵌入式版本运行,目前是 Hadoop 1.0.0。
下表总结了安装 Pig 的前提条件(0.9.1 之前我们一直在考虑 Pig 的主要版本):
|ApachePIG 版
|
先决条件
| | --- | --- | | 0.12.0 | Hadoop 0.20.2、020.203、020.204、0.20.205、1.0.0、1.0.1 或 0.23.0、0.23.1 | | Java 1.6 | | Cygwin(适用于窗户) | | Perl (for windows) | | 0.11.0,0.11.1 | Hadoop 0.20.2、020.203、020.204、0.20.205、1.0.0、1.0.1 或 0.23.0、0.23.1 | | Java 1.6 | | Cygwin(适用于窗户) | | Perl (for windows) | | 0.10.0,0.10.1 | Hadoop 0.20.2、020.203、020.204、0.20.205、1.0.0、1.0.1 或 0.23.0、0.23.1 | | Java 1.6 | | Cygwin(适用于窗户) | | Perl (for windows) | | 0.9.2 | Hadoop 0.20.2、0.20.203、0.20.204、0.20.205 或 1.0.0 | | Java 1.6 | | Cygwin(适用于窗户) | | Perl (for windows) | | 0.9.1 | Hadoop 0.20.2、0.20.203、0.20.204 或 0.20.205 | | Java 1.6 | | Cygwin(适用于窗户) | | Perl (for windows) |
Pigs 通常安装在不属于 Hadoop 集群的机器上。这可以是开发人员的机器,它连接到 Hadoop 集群。这种机器称为网关机或边缘机。
清管器的安装是一个简单的过程。从您最喜欢的发行版站点下载 Pig,无论是 Apache、Cloudera 还是 Hortonworks,并按照特定于此发行版的安装指南中指定的说明进行操作。这些说明通常包括在您选择的目录中解除 tarball 绑定的步骤,以及将唯一需要的配置(即 JAVA_HOME 属性)设置到包含 JAVA 发行版的位置的步骤。
要验证清管器安装是否正确,请尝试命令$ pig -help。
Pig 可以以两种模式运行:本地和 MapReduce。
-
The local mode: To run Pig in the local mode, install this mode on a machine where Pig is run using your local File System. The
-xlocal flag is used to denote the local mode ($ pig -x local ...). The result of this command is the Pig shell called Grunt where you can execute command lines and scripts. The local mode is useful when a developer wants to prototype, debug, or use small data to quickly perform a proof of concept locally and then apply the same code on a Hadoop cluster (the MapReduce mode).$ pig -x local ... - Connecting to ... grunt>型
下载样本代码
你可以下载你在www.packtpub.com账户购买的所有 Packt 书籍的样本代码文件。如果你是在外地买的这本书,可以访问www.packtpub.com/support注册,通过邮件直接把文件发给你。
-
The MapReduce mode: This mode is used when you need to access a Hadoop cluster and run the application on it. This is the default mode and you can specify this mode using the
-xflag ($ pigor$ pig -x mapreduce). The result of this command is the Pig shell called Grunt where you can execute commands and scripts.$ pig -x mapreduce ... - Connecting to ... grunt>您也可以执行下面的代码片段,而不是前面的代码片段:
$ pig ... - Connecting to ... grunt>
理解 Pig 是在本地和 MapReduce 模式下本地解析、检查、编译和计划的,这一点很重要。在 MapReduce 模式下,作业只能在 Hadoop 集群上执行,而在本地模式下,作业只能在本地机器上执行。这意味着在本地模式下无法证明并行性。
Pig 可以在本地和 MapReduce 模式下交互运行或以批处理模式运行。交互式运行 Pig 意味着在 Grunt shell 上执行每个命令,以批处理模式运行它意味着在 Grunt shell 上执行脚本文件(称为 Pig 脚本)中的命令组合。
下面是交互模式的一个简单示例:
grunt> raw_logs_Jul = LOAD 'NASA_access_logs/Jul/access_log_Jul95' USING ApacheCommonLogLoader AS (jaddr, jlogname, juser, jdt, jmethod, juri, jproto, jstatus, jbytes);
grunt> jgrpd = GROUP raw_logs_Jul BY DayExtractor(jdt);
grunt> DESCRIBE jgrpd;
请注意,在前面的示例中,每个 Pig 表达式都是在 Grunt shell 中指定的。以下是批处理模式执行的示例:
grunt> pigexample.pig
在前面的例子中,Pig 脚本(pigexample.pig)最初是在 Grunt shell 上创建和执行的。Pig 脚本也可以在命令提示符下在 grunt shell 之外执行。以下是如何做到这一点:
$>pig <filename>.pig (mapreduce mode)
您也可以使用下面一行代码来代替前面一行代码:
$>pig –x local <filename>.pig (local mode)
用例
本节涵盖用例的快速介绍。几乎每个基于网络的软件应用都会生成日志数据。应用将所有事件和事件的时间戳记录在日志文件中。这些事件可能包括系统配置更改、访问设备信息、用户活动和访问位置信息、警报、事务信息、错误日志和故障消息。日志中数据的价值是利用大数据处理技术实现的,在整个行业的垂直领域一致使用,了解和跟踪应用或服务行为。这可以通过发现模式、错误或次优用户体验来实现,从而将不可见的日志数据转化为有用的性能洞察。通过提供运营和业务智能的用例,可以在整个企业中利用这些见解。
下面代码列表部分的 PIG 拉丁脚本加载两个月的日志文件,分析日志,找出一个月内每天唯一的点击次数。分析出两个关系:一个是七月,一个是八月。这两种关系在每个月的某一天结合起来产生一个输出,我们可以比较每个月的日访问量(例如 7 月 1 日和 8 月 1 日的访问量)。
代码列表
以下是完整的代码列表:
-- Register the jar file to be able to use the UDFs in it
REGISTER 'your_path_to_piggybank/piggybank.jar';
/* Assign aliases ApacheCommonLogLoader, DayMonExtractor, DayExtractor to the CommonLogLoader and DateExtractor UDFs
*/
DEFINE ApacheCommonLogLoader org.apache.pig.piggybank.storage.apachelog.CommonLogLoader();
DEFINE DayMonExtractor org.apache.pig.piggybank.evaluation.util.apachelogparser.DateExtractor('dd/MMM/yyyy:HH:mm:ss Z','dd-MMM');
DEFINE DayExtractor org.apache.pig.piggybank.evaluation.util.apachelogparser.DateExtractor('dd-MMM','dd');
/* Load July and August logs using the alias ApacheCommonLogLoader into the relations raw_logs_Jul and raw_logs_Aug
*/
raw_logs_Jul = LOAD '/user/cloudera/pdp/datasets/logs/NASA_access_logs/Jul/access_log_Jul95' USING ApacheCommonLogLoader AS (jaddr, jlogname, juser, jdt, jmethod, juri, jproto, jstatus, jbytes);
raw_logs_Aug = LOAD '/user/cloudera/pdp/datasets/logs/NASA_access_logs/Aug/access_log_Aug95' USING ApacheCommonLogLoader AS (aaddr, alogname, auser, adt, amethod, auri, aproto, astatus, abytes);
-- Group the two relations by date
jgrpd = GROUP raw_logs_Jul BY DayMonExtractor(jdt);
DESCRIBE jgrpd;
agrpd = GROUP raw_logs_Aug BY DayMonExtractor(adt);
DESCRIBE agrpd;
-- Count the number of unique visits for each day in July
jcountd = FOREACH jgrpd
{
juserIP = raw_logs_Jul.jaddr;
juniqIPs = DISTINCT juserIP;
GENERATE FLATTEN(group) AS jdate,COUNT(juniqIPs) AS jcount;
}
-- Count the number of unique visits for each day in August
acountd = FOREACH agrpd
{
auserIP = raw_logs_Aug.aaddr;
auniqIPs = DISTINCT auserIP;
GENERATE FLATTEN(group) AS adate,COUNT(auniqIPs) AS acount;
}
-- Display the schema of the relations jcountd and acountd
DESCRIBE jcountd;
DESCRIBE acountd;
/* Join the relations containing count of unique visits in July and August where a match is found for the day of the month
*/
joind = JOIN jcountd BY DayExtractor(jdate), acountd BY DayExtractor(adate);
/* Filter by removing the records where the count is less than 2600
*/
filterd = FILTER joind BY jcount > 2600 and acount > 2600;
/* Debugging operator to understand how the data passes through FILTER and gets transformed
*/
ILLUSTRATE filterd;
/* Sort the relation by date, PARALLEL specifies the number of reducers to be 5
*/
srtd = ORDER filterd BY jdate,adate PARALLEL 5;
-- Limit the number of output records to be 5
limitd = LIMIT srtd 5;
/* Store the contents of the relation into a file in the directory unique_hits_by_month on HDFS
*/
STORE limitd into '/user/cloudera/pdp/output/unique_hits_by_month';
数据集
例如,我们将在美国宇航局的网络服务器上使用两个月的网络请求日志。这些日志收集于 1995 年 7 月 1 日至 31 日和 1995 年 8 月 1 日至 31 日。以下是文件中字段的描述:
- 发起请求的主机名(或互联网地址),例如,下一个代码片段中的 109.172.181.143。
- 日志名在该数据集中为空,在下一个代码片段中由
–表示。 - 用户在该数据集中为空,在下一个代码片段中用
–表示。 - 时间戳采用
DD/MMM/YYYY HH:MM:SS格式。在下面的代码片段中,时区是-0400,例如[02/Jul/1995:00:12:01 -0400]。 - HTTP 请求用引号给出,例如下一个代码片段中的
GET /history/xxx/ HTTP/1.0。 - HTTP 响应回复代码在下一个代码片段中是
200。
日志文件的片段如下:
109.172.181.143 - - [02/Jul/1995:00:12:01 -0400] "GET /history/xxx/ HTTP/1.0" 200 6545
通过代码了解 PIG
以下部分简要描述了运算符及其用法:
PIG 的延展性
在用例示例中,REGISTER函数是将外部自定义代码合并到 Pig 脚本中的三种方法之一。让我们快速了解一下本节中的另外两个 Pig 可伸缩性特性,以便更好地理解。
-
REGISTER: The UDFs provide one avenue to include the user code. To use the UDF written in Java, Python, JRuby, or Groovy, we use theREGISTERfunction in the Pig script to register the container (JAR and Python script). To register a Python UDF, you also need to explicitly provide which compiler the Python script will be using. This can be done using Jython.在我们的示例中,下面一行注册了 Piggybank JAR:
REGISTER '/opt/cloudera/parcels/CDH-4.3.0-1.cdh4.3.0.p0.22/lib/pig/piggybank.jar'; -
MAPREDUCE: This operator is used to embed MapReduce jobs in Pig scripts. We need to specify the MapReduce container JAR along with the inputs and outputs for the MapReduce program.例子如下:
input = LOAD 'input.txt'; result = MAPREDUCE 'mapreduceprg.jar' [('other.jar', ...)] STORE input INTO 'inputPath' USING storeFunc LOAD 'outputPath' USING loadFunc AS schema ['params, ... '];前面的语句使用
storeFunc来存储inputPath中名为input的关系;原生mapreduce使用storeFunc读取数据。作为执行mapreduceprg.jar的结果而接收的数据从outputPath加载到使用loadFunc作为模式的名为结果的关系中。 -
STREAM: This allows data to be sent to an external executable for processing as part of a Pig data processing pipeline. You can intermix relational operations, such as grouping and filtering with custom or legacy executables. This is especially useful in cases where the executable has all the custom code, and you may not want to change the code and rewrite it in Pig. The external executable receives its input from a standard input or file, and writes its output either to a standard output or file.运算符的语法如下:
alias = STREAM alias [, alias …] THROUGH {'command' | cmd_alias } [AS schema] ;其中
alias为关系名称,THROUGH为关键字,command为带参数的可执行文件,cmd_alias为使用DEFINE运算符为命令定义的别名,AS为关键字,schema指定模式。
代码中使用的运算符
以下是代码中使用的操作符的描述:
-
DEFINE: TheDEFINEstatement is used to assign an alias to an external executable or a UDF function. Use this statement if you want to have a crisp name for a function that has a lengthy package name.对于一个
STREAM命令,DEFINE在将可执行文件传输到 Hadoop 集群的任务节点中起着重要作用。这是使用DEFINE运算符的SHIP子句完成的。这不是我们例子的一部分,将在后面的章节中解释。在我们的示例中,我们通过名称
ApacheCommonLogLoader、DayMonExtractor和DayExtractor为相应的完全限定类名定义别名。DEFINE ApacheCommonLogLoader org.apache.pig.piggybank.storage.apachelog.CommonLogLoader(); DEFINE DayMonExtractor org.apache.pig.piggybank.evaluation.util.apachelogparser.DateExtractor('dd/MMM/yyyy:HH:mm:ss Z','dd-MMM'); DEFINE DayExtractor org.apache.pig.piggybank.evaluation.util.apachelogparser.DateExtractor('dd-MMM','dd'); -
LOAD: This operator loads data from the file or directory. If a directory name is specified, it loads all the files in the directory into the relation. If Pig is run in the local mode, it searches for the directories on the local File System; while in the MapReduce mode, it searches for the files on HDFS. In our example, the usage is as follows:raw_logs_Jul = LOAD 'NASA_access_logs/Jul/access_log_Jul95' USING ApacheCommonLogLoader AS (jaddr, jlogname, juser, jdt, jmethod, juri, jproto, jstatus, jbytes); raw_logs_Aug = LOAD 'NASA_access_logs/Aug/access_log_Aug95' USING ApacheCommonLogLoader AS (aaddr, alogname, auser, adt, amethod, auri, aproto, astatus, abytes);tuple raw_logs_Jul的内容如下:(163.205.85.3,-,-,13/Jul/1995:08:51:12 -0400,GET,/htbin/cdt_main.pl,HTTP/1.0,200,3585) (163.205.85.3,-,-,13/Jul/1995:08:51:12 -0400,GET,/cgi-bin/imagemap/countdown70?287,288,HTTP/1.0,302,85) (109.172.181.143,-,-,02/Jul/1995:00:12:01 -0400,GET,/history/xxx/,HTTP/1.0,200,6245)带球状(如
*.txt、*.csv等。),您可以读取同一目录中的多个文件(所有文件或可选文件)。在下面的例子中,文件夹Jul和Aug中的文件将作为一个联合加载。raw_logs = LOAD 'NASA_access_logs/{Jul,Aug}' USING ApacheCommonLogLoader AS (addr, logname, user, dt, method, uri, proto, status, bytes); -
STORE: TheSTOREoperator has dual purposes, one is to write the results into the File System after completion of the data pipeline processing, and another is to actually commence the execution of the preceding Pig Latin statements. This happens to be an important feature of this language, where logical, physical, and MapReduce plans are created after the script encounters theSTOREoperator.在我们的示例中,以下代码演示了它们的用法:
DUMP limitd; STORE limitd INTO 'unique_hits_by_month'; -
DUMP: TheDUMPoperator is almost similar to theSTOREoperator, but it is used specially to display results on the command prompt rather than storing it in a File System like theSTOREoperator.DUMPbehaves in exactly the same way asSTORE, where the Pig Latin statements actually begin execution after encountering theDUMPoperator. This operator is specifically targeted for the interactive execution of statements and viewing the output in real time.在我们的示例中,以下代码演示了
DUMP运算符的使用:DUMP limitd; -
UNION: TheUNIONoperator merges the contents of more than one relation without preserving the order of tuples as the relations involved are treated as unordered bags.在我们的示例中,我们将使用
UNION将两个关系raw_logs_Jul和raw_logs_Aug组合成一个名为combined_raw_logs的关系。combined_raw_logs = UNION raw_logs_Jul, raw_logs_Aug;tuple combined_raw_logs的内容如下:(163.205.85.3,-,-,13/Jul/1995:08:51:12 -0400,GET,/htbin/cdt_main.pl,HTTP/1.0,200,3585) (163.205.85.3,-,-,13/Jul/1995:08:51:12 -0400,GET,/cgi-bin/imagemap/countdown70?287,288,HTTP/1.0,302,85) (198.4.83.138,-,-,08/Aug/1995:22:25:28 -0400,GET,/shuttle/missions/sts-69/mission-sts-69.html,HTTP/1.0,200,11264) -
SAMPLE: TheSAMPLEoperator is useful when you want to work on a very small subset of data to quickly test if the data flow processing is giving you correct results. This statement provides a random data sample picked from the entire population using an arbitrary sample size. The sample size is passed as a parameter. As theSAMPLEoperator internally uses a probability-based algorithm, it is not guaranteed to return the same number of rows or tuples every timeSAMPLEis used.在我们的示例中,
SAMPLE运算符最多返回 1%的数据用于说明。sample_combined_raw_logs = SAMPLE combined_raw_logs 0.01;tuple sample_combined_raw_logs的内容如下:(163.205.2.43,-,-,17/Jul/1995:13:30:34 -0400,GET,/ksc.html,HTTP/1.0,200,7071) (204.97.74.34,-,-,27/Aug/1995:12:07:37 -0400,GET,/shuttle/missions/sts-69/liftoff.html,HTTP/1.0,304,0) (128.217.61.98,-,-,21/Aug/1995:08:59:26 -0400,GET,/images/ksclogo-medium.gif,HTTP/1.0,200,5866) -
GROUP: TheGROUPoperator is used to group all records with the same value into a bag. This operator creates a nested structure of output tuples.我们的示例中的以下代码片段说明了如何按月对日志进行分组。
jgrpd = GROUP raw_logs_Jul BY DayMonExtractor(jdt); DESCRIBE jgrpd;jgrpd 的模式内容:下面的输出显示了关系
jgrpd的模式,我们可以看到它创建了一个嵌套结构,有两个字段、键和一个用于收集记录的包。键名为group,value是与raw_logs_Jul、raw_logs_Aug组合的别名。在这个例子中。jgrpd: {group: chararray,raw_logs_Jul: {(jaddr: bytearray,jlogname: bytearray,juser: bytearray,jdt: bytearray,jmethod: bytearray,juri: bytearray,jproto: bytearray,jstatus: bytearray,jbytes: bytearray)}} agrpd = GROUP raw_logs_Aug BY DayExtractor(adt); DESCRIBE agrpd; agrpd: {group: chararray,raw_logs_Aug: {(aaddr: bytearray,alogname: bytearray,auser: bytearray,adt: bytearray,amethod: bytearray,auri: bytearray,aproto: bytearray,astatus: bytearray,abytes: bytearray)}} -
FOREACH: TheFOREACHoperator is also known as a projection. It applies a set of expressions to each record in the bag, similar to applying an expression on every row of a table. The result of this operator is another relation.在我们的示例中,
FOREACH用于迭代组中的每个数据包记录,以获得不同 IP 地址的计数。jcountd = FOREACH jgrpd { juserIP = raw_logs_Jul.jaddr; juniqIPs = DISTINCT juserIP; GENERATE FLATTEN(group) AS jdate,COUNT(juniqIPs) AS } acountd = FOREACH agrpd { auserIP = raw_logs_Aug.aaddr; auniqIPs = DISTINCT auserIP; GENERATE FLATTEN(group) AS adate,COUNT(auniqIPs) AS acount; }元组的内容:下面的输出显示了关系
jcountd和acountd中的元组。第一个字段是 DD-MMM 格式的日期,第二个字段是不同点击的次数。jcountd (01-Jul,4230) (02-Jul,4774) (03-Jul,7264) acountd (01-Aug,2577) (03-Aug,2588) (04-Aug,4254) -
DISTINCT: TheDISTINCToperator removes duplicate records in a relation.DISTINCTshould not be used where you need to preserve the order of the contents.下面的示例代码演示了使用
DISTINCT删除重复的 IP 地址,以及使用FLATTEN删除jgrpd和agrpd的嵌套。jcountd = FOREACH jgrpd { juserIP = raw_logs_Jul.jaddr; juniqIPs = DISTINCT juserIP; GENERATE FLATTEN(group) AS jdate,COUNT(juniqIPs) AS jcount; } acountd = FOREACH agrpd { auserIP = raw_logs_Aug.aaddr; auniqIPs = DISTINCT auserIP; GENERATE FLATTEN(group) AS adate,COUNT(auniqIPs) AS acount; } DESCRIBE jcountd; DESCRIBE acountd;元组的内容:下面的输出显示了
jcountd和acountd之间关系的模式。我们可以看到 T2 创造的巢穴现在已经被移走了。jcountd: {jdate: chararray,jcount: long} acountd: {adate: chararray,acount: long} -
JOIN: TheJOINoperator joins more than one relation based on shared keys.在我们的例子中,我们在一个月的某一天连接两个关系;它返回当月所有日期匹配的记录。没有找到匹配的记录将被删除。
joind = JOIN jcountd BY jdate, acountd BY adate;元组的内容:以下输出显示
JOIN执行后的结果值。此关系返回当月所有日期匹配的记录;没有找到匹配的记录将被删除。比如我们可以在FOREACH的样本输出中看到jcountd显示2-Jul被点击了 4774 次,acountd没有2-Aug的记录。因此,在JOIN之后,由于没有找到2-Aug的匹配,所以省略了命中2-Jul的元组。(01-Jul,4230,01-Aug,2577) (03-Jul,7264,03-Aug,2588) (04-Jul,5806,04-Aug,4254) (05-Jul,7144,05-Aug,2566)) -
DESCRIBE: TheDESCRIBEoperator is a diagnostic operator in Pig and is used to view and understand the schema of an alias or a relation. This is a kind of command line log, which enables us to understand how preceding operators in the data pipeline are changing the data. The output of theDESCRIBEoperator is the description of the schema.在我们的例子中,我们使用
DESCRIBE来理解模式。DESCRIBE joind;输出如下:
joind: {jcountd::jdate: chararray,jcountd::jcount: long,acountd::adate: chararray,acountd::acount: long} -
FILTER: TheFILTERoperator allows you to select or filter out the records from a relation based on a condition. This operator works on tuples or rows of data.以下示例过滤计数大于 2,600 的记录:
filterd = FILTER joind BY jcount > 2600 and acount > 2600;过滤元组的内容:过滤掉所有小于 2600 的记录。
(04-Jul,5806,04-Aug,4254) (07-Jul,6951,07-Aug,4062) (08-Jul,3064,08-Aug,4252) -
ILLUSTRATE: TheILLUSTRATEoperator is the debugger's best friend, and it is used to understand how data passes through the Pig Latin statements and gets transformed. This operator enables us to create good test data in order to test our programs on datasets, which are a sample representing the flow of statements.ILLUSTRATE内部使用一种算法,该算法使用整个输入数据的小样本,并通过 Pig 拉丁脚本中的所有语句传播数据。当遇到像FILTER这样的运算符时,算法智能生成样本数据,运算符可以从数据中删除行,导致 Pig 语句后没有数据。在我们的示例中,使用了
ILLUSTRATE运算符,如以下代码片段所示:filterd = FILTER joind BY jcount > 2600 and acount > 2600; ILLUSTRATE filterd;我们使用的数据集没有计数小于 2600 的记录。
ILLUSTRATE已进行两次计数的记录,以确保过滤掉低于 2600 的值。该记录通过了FILTER条件并被过滤掉,因此过滤后的关系中不显示任何值。以下屏幕截图显示了输出:
图形输出
-
ORDER BY:ORDERBY运算符用于对指定排序关键字的关系进行排序。到目前为止,Pig 支持对简单类型的字段进行排序,而不是复杂类型或表达式。在下面的示例中,我们基于两个字段(7 月日期和 8 月日期)进行排序。srtd = ORDER filterd BY jdate,adate PARALLEL 5; -
PARALLEL:PARALLEL操作员通过指定减速器的数量来控制减速侧的平行度。在本地模式下运行时,默认值为 1。本条款适用于强制降相的操作人员,如ORDER、DISTINCT、LIMIT、JOIN、GROUP、COGROUP、CROSS。 -
LIMIT: TheLIMIToperator is used to set an upper limit on the number of output records generated. The output is determined randomly and there is no guarantee if the output will be the same if theLIMIToperator is executed consequently. To request a particular group of rows, you may consider using theORDERoperator, immediately followed by theLIMIToperator.在我们的示例中,运算符返回五条记录作为示例:
limitd = LIMIT srtd 5;limitd元组的内容如下:(04-Jul,5806,04-Aug,4254) (07-Jul,6951,07-Aug,4062) (08-Jul,3064,08-Aug,4252) (10-Jul,4383,10-Aug,4423) (11-Jul,4819,11-Aug,4500) -
FLATTEN:FLATTEN运算符用于通过移除包和元组中的嵌套来展平它们之间的相等关系。FLATTEN的输出和使用示例请参考 distinct 中的示例代码。
解释运算符
在 Hadoop 集群中执行 pig 程序之前,会经历几个阶段,如下图所示,EXPLAIN运算符提供了最好的方式来理解 pig 拉丁代码下发生了什么。EXPLAIN运算符生成一个计划序列,用于将 PIG 拉丁脚本转换为 MapReduce JAR。
使用-dot选项生成程序的图形,该运算符的输出可以转换为图形格式。这将输出写入一个包含解释脚本执行的图表的 DOT 文件。
语法如下:
pig -x mapreduce -e 'pigexample.pig' -dot -out <filename> or <directoryname>
接下来是一个用法示例。如果我们在-out之后指定一个文件名目录,那么所有三个输出文件(逻辑、物理和 MapReduce 计划文件)都会在这个目录下创建。在下一种情况下,所有文件都将在pigexample_output目录下创建。
pig -x mapreduce -e ' pigexample.pig' -dot -out pigexample_output
根据给定的步骤将 DOT 文件转换为图像格式:
-
在您的机器上安装 graphviz。
-
通过执行以下命令来绘制用点语言编写的图形:
dot –Tpng filename.dot > filename.png
下图显示了 PIG 加工的每个步骤:
PIG 拉丁文到 Hadoop JAR
-
查询解析器:** 解析器使用另一种语言识别工具 ( Antlr ) 语言解析器验证程序语法是否正确,所有变量是否定义正确。解析器还检查模式的类型正确性,并生成中间表示, 抽象语法树 ( AST )。**
-
The logical plan: The intermediate representation, AST, is transformed into a logical plan. This plan is implemented internally as a directed graph with all the operators in the Pig Latin script mapped to the logical operators. The following diagram illustrates this plan:
逻辑计划
-
逻辑优化:检查生成的逻辑方案是否有优化机会,如过滤投影下推、列剪枝等。这些取决于剧本。执行优化,然后将计划编译成一系列物理计划。
-
The physical plan: The physical plan is a physical description of the computation that creates a usable pipeline, which is independent of MapReduce. We could use this pipeline and target other processing frameworks such as Dryad. The opportunities for optimizations in this stage are in memory aggregations instead of using combiners. The physical planning stage is also the right place where the plan is examined for the purpose of reducing the number of reducers.
为了清楚起见,每个逻辑运算符都显示有一个标识符。逻辑运算符转换生成的物理运算符以相同的标识显示。在大多数情况下,每个逻辑运算符都会变成相应的物理运算符。逻辑
GROUP运算符被映射成一系列物理运算符:局部和全局重排和打包。像 MapReduce 的Partitioner类和Reducer步骤一样,重排是通过一个键来排序的。下图显示了逻辑计划转换为物理计划的示例:
逻辑到物理计划
-
MapReduce plan: This is the phase where the physical plan is converted into a graph of actual MapReduce jobs with all the inputs and outputs specified. Opportunities for optimization in the MapReduce phase are examined to see if it is possible to combine multiple MapReduce jobs into one job for reducing the data flow between Mappers and Reducers. The idea of decoupling the Logical and Physical plans from the MapReduce plan is to divorce them from the details of running on Hadoop. This level of abstraction is necessary to port the application to a different processing framework like Dryad.
对于我们的运行示例,以下物理到映射的缩减计划显示了物理操作符在 Hadoop 阶段的分配(仅显示了映射和缩减阶段)。在 MapReduce 计划中,局部重排运算符用输入流的键和标识符解释元组。
MapReduce 计划的物理学
了解 PIG 的数据模型。
PIG 数据模型由原始类型和复杂类型组成。以下各节简要概述了这些数据类型:
原始类型
PIG 支持Int``Float``Long``DoubleT4 等原始数据类型。
复合型
下面是复杂数据类型,是原始数据类型的组合:
-
原子:一个原子包含一个值,可以由任何一种原始数据类型组成。
-
元组:一个元组就像一个行表,或者关系数据库管理系统中的一个字段序列。每个字段可以是任何数据类型,包括基本类型和复杂类型。用括号括起来,
()。示例:(163.205.85.3,-,-,13/Jul/1995:08:51:12 -0400,GET,/htbin/cdt_main.pl,HTTP/1.0,200,3585) -
包 : A 包类似于一组表和元组,元组可能重复。Bag 是 Pig 唯一可以溢出的数据结构,这意味着当整个结构不适合内存时,它会溢出到磁盘,必要时会被分页。在包中,元组的模式是灵活的,不需要有相同数量和类型的字段。由包花括号
{}中的数据或元组表示。示例:{(163.205.85.3,-,-,13/Jul/1995:08:51:12 -0400,GET,/htbin/cdt_main.pl,HTTP/1.0,200,3585) (100.305.185.30,-,-,13/AUG/1995:09:51:12 -0400,GET,/htbin/cdt_main.pl,HTTP/1.0,200,3585)} -
地图:这个是一个关键值数据结构。地图中数据项的模式没有严格执行,提供了采取任何形式的选项。Map 对于原型数据集非常有用,因为原型数据集的模式可能会随着时间的推移而改变。将地图用方括号括起来
[]。
图式的关联性
PIG 有一种特殊的方法来处理已知和未知的模式。模式的存在是通过命名字段并将其分类为数据类型来赋予字段身份。 Pig 可以通过对数据类型做出适当的假设,在运行时发现模式。如果没有分配数据类型,Pig 会将类型默认为 bytearray,然后根据使用数据的上下文执行转换。当您想要将 Pig 用于研究目的并在未知模式数据上创建快速原型时,该功能将为 Pig 带来优势。虽然使用未指定的模式有这些优点,但建议尽可能多地指定模式,以便在分析过程中更有效地检查和执行。然而,在使用各种运算符时,Pig 处理未知模式的方式有一些特殊之处。
对于执行JOIN、GROUP、UNION或CROSS的关系运算符,如果关系中有任何运算符没有指定模式,则结果关系为空。同样,当您试图展平一个具有未知模式的包时,结果将为空。
展开关于如何在 Pig 中生成空值的讨论。如前一节所述,还有其他几种通过特定运算符的交互来生成空值的方法。快速解释一下,如果比较运算符中的任何子表达式操作数,如==、<、>和MATCHES为空,结果将为空。算术运算符(如+、-、*、/)和CONCAT运算符也是如此。记住各种函数如何处理 null 之间的细微差别是很重要的。当AVG、MAX、MIN、SUM和COUNT函数忽略空值时,COUNT_STAR函数不会忽略它们,而是像有值一样计算空值。
总结
在这一章中,我们讲述了一系列的想法。中心主题是把你的注意力集中在 PIG 身上,然后探索它的外围。从 Pig 的角度,我们了解什么是设计模式,以及它们是如何被发现和应用的。我们探索了什么是 Hadoop,但我们从历史企业背景的角度进行了探索,发现了 Hadoop 是如何通过迎接传统架构的挑战来改写分布式计算的历史。
我们直观地了解了 Pig 是如何引入一种全新的 Hadoop 编程方法的,也能理解它相对于其他编程方法的优势。此外,它还为我们提供了一个用类似脚本的语言编写代码的工具,对于那些已经知道脚本或者不想用 Java MapReduce 编写代码的人来说,这很容易。通过一组小函数和运算符,它为我们提供了快速处理大量数据的能力。我们用一个代码例子来理解 Pig 的内部结构。这一节的重点是尽可能涵盖更多的领域,不要对 PIG 的探索太深入,给大家一个现成的计算器来了解 PIG。
在下一章中,我们将把对在企业中使用 Pig 的一般概念的理解扩展到具体的用例,在这些用例中,Pig 可以用于各种来源的数据输入和输出。我们将从进入企业的所有数据及其使用方式的循环视图开始,然后我们将扩展到更仔细地查看特定类型的数据,并将我们的模式应用于它。这些分支处理非结构化、结构化和半结构化数据。在每个分支中,我们将学习如何将模式应用于处理多个方面和属性的每个分支。
二、数据接收和输出模式
在前一章中,您已经了解了设计模式的高级概念,并看到了 Pig 是如何实现它们的。我们讨论了 Hadoop 和 Pig 的发展,传统系统的局限性,以及 Hadoop 和 Pig 如何与企业相关,以解决与大数据相关的具体问题。用一个现成的例子来解释 Pig 编程语言,说明了语言的特点。
我们将很快看到使用 Pig 设计模式在 Hadoop 中接收和输出各种数据的能力。本章的总体目标是作为 Hadoop 从业者的发射台,快速加载数据,尽快开始处理和分析数据,然后输出到其他系统,而不会陷入编写复杂 MapReduce 代码的迷宫。
首先,本章总结了大数据环境中常见的各种类型的数据及其来源。然后,我们讨论了几种将存储在各种源系统中的多结构数据导入 Hadoop 的数据入口设计模式。我们还将讨论将存储在 Hadoop 中的数据以本机格式导出到目标系统的数据导出设计模式。为了解释接收和输出模式,我们考虑了各种数据格式,如日志文件、图像、CSV、JSON 和 XML。用来说明这些模式的数据源是文件系统、大型机和 NoSQL 数据库。
数据接收和输出的上下文
数据摄取 是将数据输入系统进行后处理或存储的过程。这个过程包括连接到数据源,访问数据,然后将数据导入 Hadoop。导入意味着将外部来源的数据复制到 Hadoop 中,并将其存储在 HDFS。
数据导出是将数据处理后送出 Hadoop 环境的过程。输出数据的格式将与目标系统的格式相匹配。当下游系统使用数据来创建可视化、服务网络应用或网络服务或执行定制处理时,数据输出被执行。
随着 Hadoop 的出现,我们见证了以前所未有的规模快速高效地接收和输出数据的能力。企业正在根据其分析价值的需要,采用更新的示例来接收和输出数据。每一个输入企业的数据都有潜在的价值。这些提要主要由遗留企业数据、非结构化数据和外部数据组成。数据接收过程处理所有类型的提要,这些提要定期与现有的企业资产同步。数据导出处理限制出站数据,以满足集成下游系统的数据要求。
一旦数据在企业范围内,其对原始数据本身进行有意义分析的能力将得到增强,甚至在它转化为传统意义上更结构化的东西(即信息)之前。我们不再需要高度组织和结构化数据来从中收集见解。然而,随着新的老化算法的激增,任何类型或形式的数据都可以被分析。这最近导致了一种令人兴奋的商业模式,在这种模式下,企业突然发现自己正在从出于合规目的而存储多年的磁带中解压缩数据,以便发现隐藏的宝藏和价值。企业开始意识到,没有任何数据是可有可无或无用的,无论它看起来多么非结构化或无关紧要。他们已经开始争夺每一个可能给他们带来行业竞争优势的数据。
人们又对非结构化数据产生了兴趣:能否与企业现有的结构化数据源进行集成,这种集成能否通过预测性分析带来更好的业务结果。今天的数据科学家陶醉于异质性。探索非结构化数据是他们的新挑战,从随机分布中发现模式是新常态。在选定的云提供商上旋转几个 Hadoop 节点、导入数据和运行复杂的算法已经成为许多数据科学家的日常琐事。这使得处理来自许多不同来源的大量不同类型的数据变得相对简单。所有这些都强调了数据访问各种来源的重要性,这是最终价值的基础。本章我们将讨论如何通过 PIG 的设计模式摄取和排出,并给予特殊的推动力。
企业中的数据类型
下节详细介绍了以企业为中心的数据视图及其与大数据处理栈的关联,如下图所示:
企业中的数据多样性
以下是大量数据的各种类别的解释:
- 遗留数据:此数据类型包括来自所有遗留系统和应用的数据,包括在线或离线存储的结构化和半结构化数据格式。数据类型有许多用例——地震数据、飓风数据、人口普查数据、城市规划数据和社会经济数据。这些类型可以被吸收到 Hadoop 中,并与主数据相结合,以创建有趣且具有预测性的混搭。
- 事务性(OLTP)数据:来自事务性系统的数据传统上加载到数据仓库中。Hadoop 的出现解决了传统系统缺乏极致扩展性的问题。因此,事务性数据通常会被建模,以便在分析中不使用来自源系统的所有数据。Hadoop 可用于加载和分析整个 OLTP 数据,作为预处理或二次处理步骤。它还可以用来接收、输出和集成来自企业资源规划、大型机、供应链管理和客户关系管理系统的交易数据,以创建强大的数据产品。
- 非结构化数据:这种数据类型包括驻留在企业内容管理平台中的文档、笔记、备忘录和合同。这些企业系统旨在生产和存储内容,而无需大量的数据分析。Hadoop 通过发现基于上下文和用户定义的规则,为接收和处理内容提供了一个接口。内容处理的输出用于定义和设计分析,以探索使用语义技术来挖掘非结构化数据。
- 视频:很多企业已经开始使用基于视频的数据,获取安全监控、天气、媒体等相关用例的关键洞察。Hadoop 支持捕获视频中的组件,如内容、音频和相关元数据。在 Hadoop 企业数据仓库 ( EDW )中,将上下文化视频数据及关联元数据与结构化数据进行集成,进一步用先进的算法对数据进行处理。
- 音频:来自呼叫中心的数据包含了很多关于客户、比赛等类别的信息。虽然目前的数据仓库在处理和集成这种类型的数据方面有局限性,但 Hadoop 通过将其与仓库中现有的数据集成,无缝地吸收了这些数据。在 Hadoop 中,音频数据提取可以作为上下文数据和相关元数据进行处理和存储。
- 影像:静态的影像承载了大量的信息,对于政府机构(地理空间整合)、医疗(x 光和 CAT 扫描)等领域非常有用。在 Hadoop 中吸收这些数据,并将其与数据仓库集成,将通过分析洞察为大型企业带来好处,这将产生商业机会,而这些机会最初由于缺乏数据可用性或处理能力而不存在。
- 数值/图案/图形:此数据类型属于半结构化范畴。它包括地震数据、传感器数据、天气数据、股市数据、科学数据、射频识别、Hive 塔数据、车载计算机芯片、全球定位系统数据和流媒体视频。其他此类数据是出现的模式,或以周期性间隔重复列表的数字数据或图表。Hadoop 通过将结果与数据仓库相集成来帮助接收和处理这种类型的数据。这种处理将提供分析机会来执行相关性分析、聚类分析或贝叶斯类型分析,这将有助于识别收入泄漏、客户细分行为和业务风险建模中的机会。
- 社交媒体数据 : 通常归类为脸书、LinkedIn 或 Twitter 数据,社交媒体数据不止这些渠道。这些数据可以从第三方聚合商处购买,如 DataSift、Gnip 和 Nielsen。在 Hadoop 中取这些类型的数据,并与结构化数据相结合,可以实现情感检测等各种社交网络分析应用。
在接下来的章节中,我们将研究大量用于处理上述数据类型的接收和输出模式。
多结构数据的接收输出方式
以下部分描述了接收非结构化数据(图像)和半结构化文本数据(Apache 日志和自定义日志)的具体设计模式。以下是该格式的简要概述:
- Apache 日志格式:从该格式中提取信息是一个广泛使用的企业用例,并且是综合关联的。
- 自定义日志格式:此格式代表任何可以用正则表达式解析的日志。理解这种模式将有助于您将其扩展到许多其他需要编写定制加载器的类似用例中。
- 图像格式:这个是处理非文本数据的唯一模式,描述拍摄图像的模式可以调整,适用于任何类型的二进制数据。我们还将讨论图像输出模式,以说明使用 Pig 的可扩展性输出二进制数据的简单性。
摄入原木时的注意事项
日志存储取决于用例的特性。通常,在企业中,日志被存储、索引、处理并用于分析。MapReduce 的作用是索引和处理摄取的日志数据。处理后,必须存储在为日志索引实时查询提供读取性能的系统中。在本节中,我们将研究存储日志数据的各种选项,以提高实时读取性能:
- 一种选择是各种基于 SQL 的关系数据库。它们不适合为需要实时查询以获得洞察力的用例存储大量日志数据。
- 由于以下特点,NoSQL 数据库似乎是存储非结构化数据的好选择:
- 文档(如 CouchDB 和 MongoDB)将数据存储在文档中,其中每个文档可以包含可变数量的字段或模式。在日志处理的情况下,模式通常是预先确定的,不会如此频繁地改变。因此,文档数据库可以用在模式灵活性(具有不同模式的日志)是主要标准的用例中。
- 面向列的数据库,如 HBase 和 Cassandra,将密切相关的数据存储在列中,这是可扩展的。这些数据库非常适合分布式存储,并且注重性能。这些在读取操作和计算一组列时非常有效。然而,与此同时,这些数据库不如其他 NoSQL 数据库灵活。在存储数据之前,必须事先确定数据库结构。日志文件处理的最常见用例可以在面向列的数据库中实现。
- GraphLab 和 Secondary 等图形数据库是适用于日志文件处理的 Neo4j,因为日志不能表示为图形的节点或顶点。
- 像 SimpleDB 这样的键值数据库存储可以由键访问的值。当数据库方案灵活且需要频繁访问数据时,键值数据库运行良好。理想情况下,这些数据库不适合在一段时间内模式没有明显变化的日志文件处理。
考虑到上述特点,最好的做法是选择柱状数据库的性能和分发能力,而不是键值模式和文档数据库对日志文件存储和处理的灵活性。帮助做出更好决策的另一个重要标准是选择具有良好读取性能而不是良好写入性能的柱状数据库,因为必须读取和聚合数百万个日志才能进行分析。
根据所有标准,企业已经成功实施了使用 HBase 作为首选数据库的日志分析平台。
Apache 日志摄取模式
日志摄取模式描述了如何使用 pig Latin 将 Apache 日志摄取到 Hadoop 文件系统中,以在数据管道上进一步处理它们。
我们将讨论 Apache 日志与企业的相关性,并了解各种日志格式,每种格式的差异,以及日志结合 Pig 的用例。您还将了解 Pig 如何使摄取这些日志比在 MapReduce 中编程容易得多。
下面关于这个模式的实现级细节的讨论旨在让您熟悉重要的概念和适用的替代方案。一个示例代码片段用于从 Pig 语言的角度更好地理解模式,然后是使用模式的结果。
背景
Apache 服务器日志用于服务器运行状态的一般跟踪和监控。Apache 网络服务器创建 Apache 日志,并将它们存储在本地存储中。这些日志通过 Apache Flume 框架定期移动到 Hadoop 集群中,分布在 Cloudera 等主要 Hadoop 发行版中,以便存储在 Hadoop 文件系统中。
以下是 Flume 的简要介绍:
- Flume 是一个分布式的、可靠的生产者-消费者系统,用于将大量日志(配置后自动)移动到 Hadoop 进行处理。
- 接收器代理运行在 web 服务器(生产者)上。
- 代理使用收集器(使用者)定期收集日志数据。
- 代理将日志数据推送到目标文件系统 HDFS。
下图描述了此体系结构的快照:
典型测井采集
动机
分析日志数据了解并跟踪任何应用或 web 服务的行为。它包含大量关于应用及其用户的信息,这些信息被聚合以发现模式、错误或次优用户体验,从而将不可见的日志数据转化为有用的性能洞察。这些见解以特定用例的形式在整个企业中使用,从产品支持到工程和营销,提供运营和商业智能。
一个计算机集群包含许多独立的服务器,每个服务器都有自己的日志工具。这使得服务器管理员很难分析整个集群的整体性能。将每台服务器的日志文件合并成一个日志文件对于获取有关群集性能的信息非常有用。组合日志文件可以直观地显示集群的性能,并在短时间内检测集群中的问题。然而,将集群的服务器日志存储几天将产生几千兆字节的数据集。分析如此大量的数据需要大量的处理能力和内存。像 Hadoop 这样的分布式系统最适合这种处理能力和内存。
日志大小可以增长到数百 GB。Hadoop 吸收这些文件进行进一步分析,并考虑各种维度,如时间、源地理和浏览器类型,以提取模式和重要信息。
用例
该设计模式可用于以下用例:
- 找到链接到网站的用户。
- 查找网站访问者和独特用户的数量。这可以跨空间和时间维度完成。
- 在时间和空间上找出峰值负载时间。
- 分析机器人和蠕虫的访问。
- 查找与站点性能相关的统计数据。
- 分析服务器的响应和请求,深刻理解 web 服务器问题的根源。
- 分析用户对网站的哪个页面或哪个部分更感兴趣。
模式实现
通过使用 piggybank 的ApacheCommonLogLoader和ApacheCombinedLogLoader类,在 Pig 中实现了 Apache 访问日志摄取模式。这些功能扩展了 PIG 的LoadFunc水平。
代码片段
以下示例中使用的两种不同类型的日志是名为access_log_Jul95的通用日志格式和名为access.log的组合日志格式。在企业设置中,这些日志是使用生成日志的 web 服务器上的 Flume 代理提取的。
下表描述了每种类型的组成属性:
|属性
|
通用日志格式
|
组合日志格式
| | --- | --- | --- | | 国际计算机的互联网地址 | 是 | 是 | | 用户标识 | 是 | 是 | | 请求时间 | 是 | 是 | | 请求文本 | 是 | 是 | | 状态代码 | 是 | 是 | | 字节大小 | 是 | 是 | | 参考文献 | | 是 | | HTTP 代理 | | 是 |
Code of common log loader class
以下 Pig 脚本解释了如何使用CommonLogLoader类将access_log_Jul95日志文件摄取到 Pig 关系日志中:
/*
Register the piggybank jar file to be able to use the UDFs in it
*/
REGISTER '/usr/share/pig/contrib/piggybank/java/piggybank.jar';
/*
Assign the aliases ApacheCommonLogLoader and DayExtractor to piggybank's CommonLogLoader and DateExtractor UDFs
*/
DEFINE ApacheCommonLogLoader org.apache.pig.piggybank.storage.apachelog.CommonLogLoader();
DEFINE DayExtractor org.apache.pig.piggybank.evaluation.util.apachelogparser.DateExtractor('yyyy-MM-dd');
/*
Load the logs dataset using the alias ApacheCommonLogLoader into the relation logs
*/
logs = LOAD '/user/cloudera/pdp/datasets/logs/access_log_Jul95' USING ApacheCommonLogLoader
AS (addr: chararray, logname: chararray, user: chararray, time: chararray,
method: chararray, uri: chararray, proto: chararray,
status: int, bytes: int);
/*
* Some processing logic goes here which is deliberately left out to improve readability
*/
/*
Display the contents of the relation logs on the console
*/
DUMP logs;
Code of combined loader class
以下 PIG 脚本解释了如何使用CombinedLogLoader类将access.log文件摄取到 PIG 关系日志中:
/*
Register the piggybank jar file to be able to use the UDFs in it
*/
REGISTER '/usr/share/pig/contrib/piggybank/java/piggybank.jar';
/*
Load the logs dataset using piggybank's CombinedLogLoader into the relation logs
*/
logs = LOAD '/user/cloudera/pdp/datasets/logs/access.log'
USING org.apache.pig.piggybank.storage.apachelog.CombinedLogLoader()
AS (addr: chararray, logname: chararray, user: chararray, time: chararray,
method: chararray, uri: chararray, proto: chararray,
status: int, bytes: int,
referer: chararray, useragent: chararray);
/*
* Some processing logic goes here which is deliberately left out to improve readability
*/
-- Display the contents of the relation logs on the console
DUMP logs;
结果
使用这种模式的结果是,来自 Apache 日志文件的数据存储在一个包中。以下是用无效值存储 Pig 关系的几种方法:
- 如果日志文件包含无效数据,空值将存储在包中。
- 如果在
AS子句之后的模式中没有定义数据类型,那么在包中所有的列都将默认为bytearray。Pig 稍后将根据数据使用的上下文执行转换。有时需要显式键入列,以减少分析时间错误。
附加信息
- http://pig .Apache。组织/文档/r 0 .11.0/API/org/Apache/pig/PIG 库/存储/Apache 日志/组合日志加载器。html
- http://pig .Apache。组织/文档/r 0 .11.0/API/org/Apache/pig/PIG 库/存储/Apache 日志/通用日志加载器。html
- http://pig .Apache。组织/文档/r 0 .11.0/API/org/Apache/pig/pig bank/evaluation/util/Apache gpar ser/package-summary .html
本节的完整代码和数据集位于以下 GitHub 目录中:
chapter2/code/chapter2/datasets/
自定义日志摄取模式
用户自定义日志摄取模式描述如何使用 pig Latin 将任意类型的日志摄取到 Hadoop 文件系统中,以进一步处理数据管道上的日志。
我们将讨论定制日志在企业中的相关性,并了解这些日志是如何生成并传输到 Hadoop 集群的,以及日志与 Pig 相结合的用例。您还将了解 Pig 如何使摄取这些日志比在 MapReduce 中编程容易得多。
下面关于这个模式的实现级细节的讨论旨在让您熟悉重要的概念和适用的替代方案。一个示例代码片段用于从 Pig 语言的角度更好地理解模式,然后是使用模式的结果。
背景
大多数日志使用特定的约定来划分组件字段,类似于 CSV 文件,但也有我们遇到文本文件的情况,这些文件没有正确分隔(通过制表符或逗号)。这些日志在分析前需要清理。在到达 HDFS 之前,数据可以通过 Flume、Chukwa 或 Scribe 进行清理,并以 Pig 或 Hive 易于处理的格式进行存储,以便进行分析。如果数据以未清理的格式存储在 HDFS,您可以编写一个 Pig 脚本来清理数据,并将其加载到 Hive 或 HBase 中进行分析,以备后用。
动机
Pig 在处理非结构化数据方面的声誉源于其对具有部分或未知模式的数据的本地支持。加载数据时,可以选择指定模式,也可以指定加载后的模式。这与其他系统(如 Hive)形成鲜明对比,在 Hive 中,您必须在加载之前强制实施模式。
当文本数据尚未标准化和格式化时,使用此模式。
用例
以下是可以应用这种模式的一般用例:
- 接收任何没有明确定义模式的文本或日志文件。
- 获取文本或日志文件,并根据分析的适用性实验性地找出可以强加给它们的模式。
模式实现
利用 piggybank 的TextLoader功能,在 Pig 中实现了非结构化文本的摄入模式。这些函数继承了LoadFunc类。
Pig 有一个很好的特性,如果没有显式指定模式,它可以解释数据的类型。在这种情况下,字段被设置为默认的bytearray类型,然后根据下一条语句中数据的用法和上下文推断出正确的类型。
Piggybank 的TextLoader功能可以加载文本文件,将它们拆分成新的行,并将每一行加载到 Piggybank 元组中。如果模式是用AS子句指定的,那么每个元组都被认为是chararray。如果省略号子句没有指定模式,则结果元组将没有该模式。
同样,使用指定的正则表达式模式过滤行后,可以使用MyRegexLoader类加载文件内容。可以使用MyRegExLoader指定正则表达式格式。如果一个模式作为参数传递给它,这个函数返回一个匹配的正则表达式chararray。
代码片段
在这个用例中,我们说明了应用日志文件的摄取,并通过分析请求/响应模式来帮助识别 web 服务器中潜在的性能问题。我们将使用sample_log.1数据集来计算每个服务的平均响应时间。日志文件包含嵌入的事件日志以及 web 应用生成的 web 服务请求和响应信息。格式如下面的代码所示。这里,我们只对提取请求-响应对感兴趣,忽略了与 info、DEBUG 和 ERRORS 相关的事件信息:
/* other unstructured event logs related to INFO, DEBUG, and ERROR logs are depicted here */
Request <serviceName> <requestID> <Timestamp>
Response <serviceName> <requestID> <Timestamp>
/* other unstructured event logs related to INFO, DEBUG, and ERROR logs are depicted here */
下面的代码片段显示了使用MyRegexLoader加载与指定正则表达式匹配的行:
/*
Register the piggybank jar file to be able to use the UDFs in it
*/
REGISTER '/usr/share/pig/contrib/piggybank/java/piggybank.jar';
/*
Load the logs dataset using piggybank's MyRegExLoader into the relation logs.
MyRegexLoader loads only the lines that match the specified regex format
*/
logs = LOAD '/user/cloudera/pdp/datasets/logs/sample_log.1'
USING org.apache.pig.piggybank.storage.MyRegExLoader(
'(Request|Response)(\\s+\\w+)(\\s+\\d+)(\\s+\\d\\d/\\d\\d/\\d\\d\\s+\\d\\d:\\d\\d:\\d\\d:\\d\\d\\d\\s+CST)')
AS (type:chararray, service_name:chararray, req_id:chararray, datetime:chararray);
/*
* Some processing logic goes here which is deliberately left out to improve readability
*/
-- Display the contents of the relation logs on the console
DUMP logs;
进一步处理将在提取的日志上完成,以计算每个服务的平均响应时间并识别潜在的性能问题。
以下代码片段显示了使用TextLoader加载自定义日志:
/*
Load the logs dataset using TextLoader into the relation logs
*/
logs = LOAD '/user/cloudera/pdp/datasets/logs/sample_log.1' USING TextLoader AS (line:chararray);
/*
The lines matching the regular expression are stored in parsed_logs.
FILTER function filters the records that do not match the pattern
*/
parsed_logs = FILTER logs BY $0 MATCHES '(Request|Response)(\\s+\\w+)(\\s+\\d+)(\\s+\\d\\d/\\d\\d/\\d\\d\\s+\\d\\d:\\d\\d:\\d\\d:\\d\\d\\d\\s+CST)';
/*
* Some processing logic goes here which is deliberately left out to improve readability
*/
-- Display the contents of the relation parsed_logs on the console
DUMP parsed_logs;
结果
使用此模式的结果是,日志文件中的数据存储在包中。该袋用于后续分析步骤。
以下是用无效值存储 Pig 关系的几种方法:
- 如果日志文件包含无效数据,空值将存储在包中。
- 如果在
AS子句之后的模式中没有定义数据类型,那么在包中所有的列都将默认为bytearray。Pig 稍后将根据使用数据的上下文执行转换。有时需要显式键入列,以减少分析时间错误。- 您可以在
AS子句后定义数据类型,但是在为每列定义适当的数据类型时必须小心。当无法进行数据类型转换时,包中会存储空值,例如chararray类型强制转换为int类型,导致空值。但是int可以铸造成chararray。(例如int 27可以打成chararray "27"。)
- 您可以在
- 您必须特别注意可能导致关系中出现空值的数据。像
COUNT这样的关系运算符会忽略空值,但是COUNT_STAR函数不会忽略它,而是将空值视为有价值的值。
附加信息
- http://pig .Apache。组织/文档/r 0 .11.0/API/org/Apache/PIG 库/仓储/my regex 加载程序 html
- pig.apache.org/docs/r0.11.…
本节的完整代码和数据集可以在以下 GitHub 目录中找到:
chapter2/code/chapter2/datasets/
图像输入和输出模式
本节设计模式描述了如何使用 Pig Latin 在 Hadoop 文件系统中捕获并输出一组图像,以进一步处理数据管道中的图像。
我们将讨论图像在企业中的相关性,并了解创建和存储图像的各种方法,收集要在 Hadoop 上处理的图像的最佳方式,以及将图像与 Pig 相结合的用例。您还将学习 Pig 如何使用用 Java 编写的自定义 UDF 轻松捕获这些图像。
下面关于这个模式的实现级细节的讨论旨在让您熟悉重要的概念和适用的替代方案。一个示例代码片段用于从 Pig 语言的角度更好地理解模式,然后是使用模式的结果。
背景
Hadoop 有许多处理结构化数据和非结构化文本数据的记录用例。然而,我们有证据表明,许多情况下使用 Hadoop 的真正力量来处理其他形式的非结构化数据,如图像、视频和声音文件。
在图像处理方面,Hadoop 在分析气象/军事/民用卫星拍摄的图像时,即当图像尺寸大、分辨率高,需要由一组服务器进行处理时,起到了关键作用。
Hadoop 为大图像或一组小图像提供了有效的存储机制。不同于在 RDBMS 中将图像存储为 BLOB 的过程,无法通过 SQL 进行大规模、有意义的分析,可以在 Hadoop 上编写特定的图像处理算法,可以处理单个图像和一组图像,并行进行高端的图像分析。
动机
这种模式适合在 Hadoop 中加载和处理大量的图像文件。将图像加载到数据管道中是由一个用 Java 编写的 UDF 完成的。
图像入口和出口
获取非结构化图像数据,并将其与提供上下文信息的结构化图像元数据(如标签、EXIF 信息和对象标签)相结合,导致社交媒体分析和其他领域(如安全、情报收集、天气预报和人脸识别)的更新和发展。这个想法可以扩展到更广泛的图像特征,使我们能够以革命性的方式检查和分析图像。
图像导入 Hadoop 后,原始图像的实际处理是一项复杂的任务,涉及原始像素级的多次计算。这些计算是由低级的 C 和 C++算法完成的。Hadoop 与这些算法集成,使用 Hadoop 流包装这些算法,并作为标准 Hadoop 作业工作。
图像输出模式试图展示一种简单的机制,其中作为序列文件存在于 HDFS 的二进制图像作为图像文件输出。这种模型的动机在于,基于 Hadoop 的图像处理算法可以对图像进行复杂的计算,以连接其组件来创建更大的图像。
Hadoop 通过将图像文件分组为少量的大文件而不是大量的小图像文件来有效地工作。使用大量小图像文件(其大小小于 64 MB 的 HDFS 块大小)可能会导致从磁盘读取大量数据并搜索名称节点,这可能会导致大量网络流量将这些文件从一个节点传输到另一个节点。这将导致无效的数据访问。这种设计模式探索了一种通过在 Hadoop 中将这些图像文件分组为序列文件来克服这种限制的方法。您可以扩展此模式来接收和处理其他类型的二进制文件,如声音和视频。
拍摄设计模式适用于作为图像文件的大语料库的一部分的图像,其中每个图像都是不同的,将它们组合在一起是不自然的。这种模式不适合在 Hadoop 集群的节点之间划分非常大的映像。上图显示了该架构的示意图。
用例
您可以考虑在以下用例中应用图像捕获模式作为预处理步骤:
- 捕获多个图像,以对每个图像应用各种类型的图像过滤器。
- 图像质量的批量增强
- 理解图像的内容,例如,应用基于人工智能的无监督计算机视觉算法从图像中提取道路、运河或建筑物等特征。
- 使用图像进行模式匹配,例如医学和地理信息系统图像。
您可以考虑在必须从图像中去除噪声的用例中应用图像导出模式。将原始图像加载到 Hadoop 中并进行处理以去除噪声;通过组合图像的多个块来创建新图像,并且返回被噪声过滤的图像。
模式实现
下一节介绍图像捕捉模式和图像输出模式的模式实现。
影像门户的实现
使用自定义加载器函数在 Pig 中实现图像捕获模式,在 Java 中实现为 UDF 函数。这ImageToSequenceFileUDF将图像转换成序列文件。输入是图像目录的 HDFS 路径,输出是序列文件的路径。
序列文件将图像文件的内容存储为映射到文件名关键字的值。因为序列文件可以拆分,所以可以通过流式传输或使用 MapReduce 进行处理。MapReduce 在内部使用一个标签将文件划分成块大小的块,并独立操作。文件可以被许多编解码器压缩,块压缩用于最大限度地提高存储和检索效率。在这种情况下,将没有解压缩器来防止数据洗牌和带宽消耗。当序列文件中存储大量图像数据时,这将使 Hadoop 的可伸缩优势得以利用。
图像导出的实现
Image 导出模式利用自定义存储功能在 Pig 中实现,在 Java 中实现为 UDF。这个SequenceToImageStorage类将序列文件转换成图像,并将其存储在磁盘上的指定位置。这个函数的输入是序列文件的路径。
代码片段
以下部分描述了图像捕获模式的代码,后面是图像退出。
图像输入
为了解释这种模式是如何工作的,我们考虑一组存储在 HDFS Hadoop 文件系统可访问的文件夹中的图像文件。图像未经预处理;它们以原始格式(JPEG)存储。下面的代码有两个主要部分。首先是 Pig Latin 脚本,它加载包含 images 文件夹路径的文件,其次是用 Java 编写的自定义 UDF,它实际上在幕后工作,将一个图像或一组图像分解成序列文件。
PIG
以下是读取图像文件并将其转换为序列文件的 Pig 脚本:
/*
Register the custom loader imagelibrary.jar, it has UDFs to convert images to sequence file and sequence file to images
*/
REGISTER '/home/cloudera/pdp/jars/imagelibrary.jar';
/*
Load images_input file, it contains the path to images directory
*/
images_file_path = LOAD '/user/cloudera/pdp/datasets/images/images_input' AS (link:chararray);
/*
ImageToSequenceFileUDF converts multiple image files to a sequence file.
This ensures that there are no large number of small files on HDFS, instead multiple small images are converted into a single sequence file.
Another advantage of sequence file is that it is splittable.
The sequence file contains key value pairs, key is the image file name and value is the image binary data.
It returns the path of the sequence file.
*/
convert_to_seq = FOREACH images_file_path GENERATE com.mycustomudf.ImageToSequenceFileUDF();
/*
* Some processing logic goes here which is deliberately left out to improve readability
*/
-- Display the contents of the convert_to_seq on the console
DUMP convert_to_seq;
图像到序列 UDF 片段
以下是ImagetoSequenceFileUDF 的 Java 代码片段,展示了从图像文件到序列文件的转换:
public static String createSequenceFile(Path inPutPath)
{
.
.
for(int i=0;i<status.length;i++)
{
//FSDataInputStream is opened at the given path
dataInputStream = fileSystem.open(status[i].getPath());
// extracting image name from the absolute path
fileName = status[i].getPath().toString().
substring(status[i].getPath().toString().
lastIndexOf("/")+1);
byte buffer[] = new byte[dataInputStream.available()];
//buffer.remaining() bytes will be read into buffer.
dataInputStream.read(buffer);
/*Add a key/value pair. Key is the image filename and
value is the BytesWritable object*/
seqFileWriter.append(new Text(fileName),
new BytesWritable(buffer));
.
.
}
}
图像退出
下一节描述图像退出的代码。
PIG
以下是将序列文件的内容输出到图像的 Pig 脚本:
/*
Register the custom jar, it has UDFs to convert images to sequence file and sequence file to images
*/
REGISTER '/home/cloudera/pdp/jars/imagelibrary.jar';
/*
Load images_input file, it contains the path to images directory
*/
images_file_path = LOAD '/user/cloudera/pdp/datasets/images/images_input' AS (link:chararray);
/*
ImageToSequenceFileUDF function converts multiple image files to a sequence file.
This ensures that there are no large number of small files on HDFS, instead multiple small images are converted into a single sequence file.
Another advantage of sequence file is that it is splittable.
The sequence file contains key value pairs, key is the image file name and value is the image binary data.
It returns the path of the sequence file.
*/
convert_to_seq = FOREACH images_file_path GENERATE com.mycustomudf.ImageToSequenceFileUDF();
/*
* Some processing logic goes here which is deliberately left out to improve readability.
* It is assumed that in-between the load and store steps, a user performs some image processing step such as stitching multiple image tiles together.
*/
/*
The custom UDF SequenceToImageStorage reads the sequence file and writes out images.
It reads each key/value pair and writes out the contents as images with keyname as the filename in the folder seq_to_img_output
*/
STORE convert_to_seq INTO '/user/cloudera/pdp/output/images/seq_to_img_output' USING com.mycustomudf.SequenceToImageStorage();
序列对 UDF 进行成像
以下是自定义存储功能SequenceToImageStorage和的片段,用于读取序列文件并将内容写入图像文件:
@Override
public void putNext(Tuple tuples) throws IOException {
.
.
// Do this for each key/value pair
while (seqFilereader.next(key, value))
{
bufferString = value.toString().split(" ");
buffer =new byte[bufferString.length];
for(int i=0;i<bufferString.length;i++)
{
/*
String parameter parsed as signed integer in the radix given by the second parameter
*/
buffer[i] = (byte)
Integer.parseInt(bufferString[i], 16);
}
/*
output path of the image which is the path specified, key is the image name
*/
outPutPath=new Path(location+"/"+key);
// FSDataOutputStream will be created at the given Path.
seqFileWriter = fileSystem.create(outPutPath);
// All bytes in array are written to the output stream
seqFileWriter.write(buffer);
}
.
.
}
Hadoop API 的SequenceFile.Reader类用于读取序列文件,获取键值对。迭代键值对,然后为每个键值对创建一个带有键名的新文件,并将该值作为字节写入文件,从而生成多个图像文件。
结果
作为应用图像捕获模式的结果,图像语料库被 Java UDF 解析成序列文件。然后将每个序列文件分解为 RGB 值,并存储在 PIG 拉丁映射关系中。数据管道的下一阶段使用映射关系来进一步处理序列文件。
作为图像输出模式的结果,存储在 HDFS 的序列文件被转换成图像文件,使得上游图像显示系统可以使用这些图像。
附加信息
- http://pig .Apache。组织/文档/r 0 .11.0/API/org/Apache/pig/pig bank/storage/sequence fileloper .html
- http://pig。 Apache. Organization/document /r 0. 11 .1 UDF。 Html # Load-Store-Function
本节的完整代码和数据集位于以下 GitHub 目录中:
chapter2/code/chapter2/datasets/
nosql 数据的导入和导出模式
本节描述了从两种类型的 NoSQL 数据中获取数据的模式。为了说明 Pig 随时支持 NoSQL 数据库的能力及其相关用例,我们选择了 MongoDB 等文档数据库和 HBase 等柱状数据库。
MongoDB 出入口模式
MongoDB 导入导出模式描述了如何使用 Pig 拉丁语将 MongoDB 文档集合的内容存储在 Hadoop 文件系统(Pig 关系)中进行数据处理,然后将处理后的数据写回 MongoDB。
我们将讨论存储在 MongoDB 中的数据与企业之间的相关性,并了解访问 MongoDB 数据的各种方式、接收和输出的动机,以及 MongoDB 数据与 Pig 相结合的用例。您还将学习 Pig 如何比用 Java 编写的 MapReduce 代码更直观地接收和导出这些数据。
下面关于这个模式的实现级细节的讨论旨在让您熟悉重要的概念和适用的替代方案。示例代码片段可以从 Pig 语言的角度更好地理解模式和使用模式的结果。
背景
Godb 是一个 NoSQL 数据库,从头开始设计,以文档集合的形式存储数据,不同于 RDBMS 的行列。由于其广泛的索引功能和使用 JSON 与外部应用的集成,它具有很高的可扩展性,并使文档检索变得容易。MongoDB 非常灵活,可以处理可变模式。(集合中的每个文档不必具有相同的架构。)因为 MongoDB 将数据存储为文档,并且这些文档集合的几乎所有属性都被索引,所以作为处理实时查询的操作存储,它是一个非常有效的解决方案。与 Hadoop 不同,Hadoop 擅长离线批处理和聚合各种来源的数据。
动机
在典型的企业中,MongoDB 和 Hadoop 在某些场景下是集成的。在这些场景中,Hadoop 需要处理比 MongoDB 更极端的数据负载,以聚合数据并促进复杂的分析。
来自 MongoDB 的数据被吸收到 Hadoop 中,并用 MapReduce 作业进行处理。Hadoop 使用 Pig 数据管道将数据与来自其他企业来源的附加数据相结合,以开发多数据聚合解决方案。对 Pig 数据管道中的数据进行处理后,写回 MongoDB 进行具体的分析和查询。这确保了现有应用可以使用从 Hadoop 导出的数据来创建可视化或驱动其他系统。
在许多企业用例中,Hadoop 作为一个中央数据存储库,将数据与不同的数据存储集成在一起。在这种情况下,通过使用 MapReduce 作业,MongoDB 可以用作定期向 Hadoop 提供数据的数据源之一。一旦 MongoDB 数据被吸收到 Hadoop 中,合并后的较大数据集就会被处理,并可用于进一步查询它们。
MongoDB 也是运营数据仓库 ( ODS )之一,连接其他数据仓库和数据仓库。获取分析见解包括从这些连接的数据源移动数据和执行 ETL。PIG 可以有效地用于这一目的。Hadoop 充当 ETL 中枢,从一个存储中提取数据,使用 MapReduce 作业执行各种转换,并将数据加载到另一个存储中。
注
应该注意的是,与已经加载/传输到 HDFS 的数据相比,直接从外部来源(MongoDB)获取的数据具有非常不同的操作性能特征。
用例
您可能要考虑在以下场景中使用数据导入导出模式,其中 MongoDB 和 Hadoop 的集成将获得丰厚的回报:
- MongoDB 和 Hadoop 分别处理接近实时和批处理的不同工作负载。在您想要将负载卸载到 Hadoop 进行批处理的用例中,考虑使用门户设计模式,从而释放 MongoDB 中的资源。考虑使用导出设计模式,使 MongoDB 成为从 Hadoop 导出数据并支持实时查询操作的接收器。
- MongoDB 本身有一个在 MongoDB 数据库上运行的 MapReduce 实现。然而,它比 Hadoop MapReduce 慢,因为它是用 JavaScript 实现的,而且它执行复杂分析的数据类型和库更少。考虑在需要将数据卸载到 Hadoop 的用例中使用门户设计模式,以利用 Hadoop 的库支持、机器学习、ETL 功能和处理规模。考虑使用导出设计模式将数据从 Hadoop 移动到 Mongo DB,并使用 MongoDB 的 MapReduce 实现。
- MongoDB 支持很少的基本数据聚合函数来生成 SQL 风格的聚合,这就需要更高的学习曲线来理解聚合框架。如果您想使用 Hadoop 执行复杂的聚合任务,请考虑使用门户设计模式。
- 当存在大量非结构化数据并且需要 MongoDB 进行实时分析时,可以使用这种设计模式。在这种情况下,可以使用导入设计模式将 Hadoop 中摄取的原始数据创建一个结构,并使用导出设计模式将数据导出到 MongoDB 中,以促进 MongoDB 中的优化存储,从而进行实时查询和分析。
模式实现
下图显示了 MongoDB 连接器集成:
MongoDB 连接器集成
您可以使用 Hadoop 的 MongoDB 连接器来集成 Hadoop 和 MongoDB。这个连接器有助于将数据从 MongoDB 转移到 Hadoop 生态系统,并允许通过其他编程语言(Hadoop 流)进行访问。连接器与 Pig 的集成如上图所示。
进入实施
Pig 使用 MongoLoader函数将 MongoDB 数据加载到 Pig 的拉丁关系中。使用这个函数,数据直接从数据库加载。Pig 也可以使用BSONLoader功能读取 MongoDB 原生格式(BSON)。
MongoLoader函数可以在非模态模式下工作,无需指定字段名。在这种模式下,记录被解释为包含单个映射(文档)的元组。当您不知道 MongoDB 集合的模式时,这很有用。MongoLoader该功能也可以在模式模式下工作,在该模式下可以指定将 Pig 脚本中的字段与文档中的字段进行映射的字段名。
出口变现
PIG 关系中的数据可以通过两种方式写入 MongoDB。第一种方法是使用BSONStorage函数在.BSON文件中存储一个关系,以后可以导入 MongoDB。这种方法的优点是以 MongoDB 的本地存储格式写入,具有高吞吐量。第二种方法使用 MongoDB 的包装器将连接到数据库,并使用MongoStorage函数将其直接写入数据库。该函数将在元组级别运行,并将它接收的每个元组存储到 MongoDB 中的相应文档中。在写之前,已经映射了 Pig 关系和 MongoDB 文档的模式。使用第二种方法将为您在记录或元组级别写入数据提供极大的灵活性,但它会影响输入/输出速度。
MongoStorage该函数还可以通过在构造函数中指定更新键来更新 MongoDB 中已有的文档集合。如果指定了更新关键字,则对应于该关键字的第一个文档(值)将被 Pig 元组的内容更新。
代码片段
在下面的示例代码中,我们考虑已经驻留在 MongoDB 中的nasdaqDB.store_stock数据的内容。数据集包括 20 世纪 70 年代至 2010 年纳斯达克数据;这包括各种公司的股票跟踪数据以及它们在特定一天的交易量数据中的表现。数据集按照跑马灯符号的字母顺序组织,并作为 JSON 对象存储在 MongoDB 中。
进入码
下面的代码通过将 MongoDB 文档的字段映射到模式中指定的字段,执行连接到 MongoDB、建立连接、加载 MongoDB 本地文件、解析它以及仅检索在MongoLoader构造函数中指定的模式的任务。这个抽象是通过调用MongoLoader函数来实现的。
/*
Register the mongo jar files to be able to use MongoLoader UDF
*/
REGISTER '/home/cloudera/pdp/jars/mongo.jar';
REGISTER '/home/cloudera/pdp/jars/mongo-hadoop-pig.jar';
/*
Load the data using MongoLoader UDF, it connects to MongoDB, loads the native file and parses it to retrieve only the specified schema.
*/
stock_data = LOAD 'mongodb://slave1/nasdaqDB.store_stock' USING com.mongodb.hadoop.pig.MongoLoader('exchange:chararray, stock_symbol:chararray, date:chararray, stock_price_open:float, stock_price_high:float, stock_price_low:float, stock_price_close:float, stock_volume:long, stock_price_adj_close:chararray') AS (exchange,stock_symbol,date,stock_price_open,stock_price_high,stock_price_low,stock_price_close,stock_volume,stock_price_adj_close);
/*
* Some processing logic goes here which is deliberately left out to improve readability
*/
/*
Display the contents of the relation stock_data on the console
*/
DUMP stock_data;
导出代码
以下代码描述了将stock_data pig 中存在的数据写入 MongoDB 文档集合:
/*
Register the mongo jar files and piggybank jar to be able to use the UDFs
*/
REGISTER '/home/cloudera/pdp/jars/mongo.jar';
REGISTER '/home/cloudera/pdp/jars/mongo_hadoop_pig.jar';
REGISTER '/usr/share/pig/contrib/piggybank/java/piggybank.jar';
/*
Assign the alias MongoStorage to MongoStorage class
*/
DEFINE MongoStorage com.mongodb.hadoop.pig.MongoStorage();
/*
Load the contents of files starting with NASDAQ_daily_prices_ into a Pig relation stock_data
*/
stock_data= LOAD '/user/cloudera/pdp/datasets/mongo/NASDAQ_daily_prices/NASDAQ_daily_prices_*' USING org.apache.pig.piggybank.storage.CSVLoader() as (exchange:chararray, stock_symbol:chararray, date:chararray, stock_price_open:chararray, stock_price_high:chararray, stock_price_low:chararray, stock_price_close:chararray, stock_volume:chararray, stock_price_adj_close:chararray);
/*
* Some processing logic goes here which is deliberately left out to improve readability
*/
/*
Store data to MongoDB by specifying the MongoStorage serializer. The MongoDB URI nasdaqDB.store_stock is the document collection created to hold this data.
*/
STORE stock_data INTO 'mongodb://slave1/nasdaqDB.store_stock' using MongoStorage();
结果
作为在 MongoDB 文档集合上应用摄取设计模式的结果,MongoDB URI 指定的集合的内容被加载到stock_dataPIG 关系中。同样,导出设计模式将stock_dataPIG 关系的内容存储到nasdaqDB.store.stock蒙古文数据库文档集合中。
以下方式具体到MongoLoader的实现,可以用无效值存储 Pig 关系:
- 如果输入的 MongoDB 文档包含一个未在构造函数模式下映射的字段,
MongoLoader函数将在 Pig 关系中存储该字段的空值。 - 如果 MongoDB 文档不包含构造函数模式中指定的字段,则关系的整行或元组将被设置为 null。
- 如果 MongoDB 文档字段和指定模式之间存在类型不匹配,则
MongoLoader将在 Pig 关系中将该字段设置为空。
附加信息
本节的完整代码和数据集位于以下 GitHub 目录中:
chapter2/code/chapter2/datasets/
糖化血红蛋白的进出方式
HBase 的导入导出模式描述了如何使用 Pig 拉丁语将 HBase 表的内容摄取到 Pig 关系中,对数据进行进一步处理,再将处理后的数据导出到 HBase。
我们将讨论糖化血红蛋白与企业的相关性,了解糖化血红蛋白数据的各种内部存储和外部访问方式,以及糖化血红蛋白数据结合 Pig 的使用案例。您还将了解 Pig 如何通过提供现成的功能来更轻松地导入和导出 HBase 数据。
下面关于这个模式的实现级细节的讨论旨在让您熟悉重要的概念和适用的替代方案。样例代码片段可以从 Pig 语言的角度更好地理解模式,进而是使用模式的结果。
背景
HBase 是一个面向列的 NoSQL 数据库,其灵感来源于 Google 实现的 Big Table,专门设计用于以灵活的模式存储数据并实时访问。它对于包含数十亿列的数据是线性可伸缩的,并且具有数据压缩和快速访问的内存操作功能。
在 HDFS,糖化血红蛋白数据以定制的优化格式存储在内部,称为索引存储文件。HBase 使用 HDFS 来利用其存储和高可用性功能。由于 HDFS 无法存储数据来执行随机读写,因此 HBase 使用针对随机读写访问优化的二进制格式来克服 HDFS 的限制。在 HDFS 存储 HBase 索引存储文件,非常适合 MapReduce 在不从其他地方导入数据的情况下在上面工作。
逻辑上,HBase 将数据存储在一个嵌套的多维映射抽象中,该抽象具有排序的键值对和与键值相关联的时间戳。时间戳使最新版本的数据能够以有序的顺序存储,以便于搜索。HBase 实现了快速和慢速变化数据的概念,因此可以使用版本来相应地存储它们。多维嵌套映射中的数据是通过使用主键来检索的,主键在 HBase 中称为 rowkey,可用于取消引用所有嵌套数据。
多维映射有两个重要的嵌套结构(实现为映射),称为列族和属于列族的列。列族的架构在存储生命周期中不能更改,而列族中列的架构可以有灵活的架构,每行可以更改一次。这种数据组织本质上适合存储不相关的适合实时访问的非结构化数据(因为一切都在地图中)。
动机
需要将 HBase 表摄取到 Pig 中,有助于用 MapReduce 框架对其进行批处理,达到用例目标。在 PIG 数据管道中处理糖化血红蛋白数据后,有时需要将其存储回糖化血红蛋白中,以便实时访问在糖化血红蛋白上运行的查询。正是在这样的背景下,HBase 数据的导入和导出模式显得尤为诱人。
HBase 中的数据通过 HBase Java 客户端的应用编程接口在本地访问,放入并获取数据。这个应用编程接口非常适合与需要实时查询能力的外部应用集成。但是,API 没有能力执行批处理数据处理来创建数据聚合和复杂的管道来生成分析意见。这种批处理能力伴随着低层次的抽象,如 MapReduce 或 Pig 的高级灵活性。
您可以编写 Java MapReduce 作业来访问存储在 HBase 中的数据并进行处理,但与必须编写 Java 代码来访问 HBase 中的数据相比,Pig 在简单性和简洁优化的代码方面得分很高。
通过 Pig 中的运算符访问存储在 HBase 中的数据,可以对 Pig 数据管道中的数据进行操作,并使用批处理对其进行转换。将 Pig 关系中的数据存储到 HBase 中,使 HBase 能够为应用提供实时查询数据的权利。
由于数据以索引存储文件的形式驻留在 HDFS,因此有必要告诉 Pig 如何以 Pig 能够理解和处理的方式将数据序列化和反序列化为 HBase 格式。Pig 需要清楚地知道如何在列族、HBase 抽象中的列和 Pig 的原生数据类型之间进行转换。该模式说明了如何使用HBaseStorage pig 功能完成向/从 HBase 摄取和导出数据的任务。
注
与 MongoDB 示例不同,这里我们读取了已经存储在 HDFS 的 HBase 文件。我们不连接到 HBase 服务器,也不通过网络从它们读取数据。
用例
以下是 Pig 从 HBase 接收和输出数据的一个用例:
- 使用摄取设计模式创建一个数据管道,以集成驻留在 HBase 中的实时数据来执行分析。
- 使用摄取设计模式访问 HBase 中的数据,以便在 Pig 中为下游系统执行高级数据聚合。Pig 可以作为一个 ETL 中枢来转换 HBase 中的数据,并将其与其他应用的数据集成在一起。
- 使用导出设计模式将 HDFS 现有平面文件的内容存储到一个 HBase 表中。对于实时查询,这种模式对于在 HBase 中存储复杂数据集成或转换管道的结果也很有用。
模式实现
下面一节介绍 HbA1c 摄入模式的模式实现,后面是 HbA1c 输出。
进入实施
hbase 中的数据可以通过以下两种方式获取:
- 第一种选择是用并行读取的 MapReduce
EXPORT job导出整个表,从而将表的内容导出到 HDFS 序列文件。反序列化程序可以用 Java 或 Pig 编写,以访问序列文件的内容,供以后操作。这个选项有点难以实现,因为我们必须从后端访问 HBase 的内容,然后反序列化文件。此外,这可以一次处理一个表并访问多个表;必须重叠的列表。 - 第二种选择是实现 HBase 进气设计模式,使用 Pig
HBaseStorage的内置加载功能。这是一个连接到 HBase 表并将表的内容直接放入 Pig 关系的简单选项。Pig 负责将 HBase 类型映射到 Pig 类型的反序列化任务和并行导入的 MapReduce 作业。HBaseStorage还有一个优点,就是将数据加载到 Pig 关系中,使用所有列族或者只使用列族的列子集。因为列包含键值类型,所以它们可以按类型转换为 Pig 的映射类型。
出口变现
Pig 使用HBaseStorage功能实现导出设计模式。除了使用STORE子句之外,该模式与摄取模式的实现非常相似。STORE子句向 Pig 编译器传达要从指定的 Pig 关系中提取什么数据,并将其序列化到参数中的 HBase 表中。
下图说明了入口和出口实施选项:
糖化血红蛋白酶与 PIG 的整合
代码片段
下面的代码示例使用了一个包含零售交易复合样本的数据集。包含 T0、T1、T2、T10、T3、T4、T5、T6 等属性。该数据已存储在 HBase 中,以说明此示例。糖化血红蛋白表hbase://retail_transactions通过 PIG 拉丁的HBaseStorage功能进入。
进入码
下面的代码片段说明了摄入 PIG 的糖化血红蛋白数据之间的关系:
/*
Load data from HBase table retail_transactions, it contains the column families transaction_details, customer_details and product_details.
The : operator is used to access columns in a column family.
First parameter to HBaseStorage is the list of columns and the second parameter is the list of options
The option -loadkey true specifies the rowkey should be loaded as the first item in the tuple, -limit 500 specifies the number of rows to be read from the HBase table
*/
transactions = LOAD 'hbase://retail_transactions'
USING org.apache.pig.backend.hadoop.hbase.HBaseStorage(
'transaction_details:transaction_date customer_details:customer_id customer_details:age customer_details:residence_area product_details:product_subclass product_details:product_id product_details:amount product_details:asset product_details:sales_price', '-loadKey true -limit 500')
AS (id: bytearray, transaction_date: chararray, customer_id: int, age: chararray, residence_area: chararray, product_subclass: int, product_id: long, amount: int, asset: int, sales_price: int);
/*
* Some processing logic goes here which is deliberately left out to improve readability
*/
-- Display the contents of the relation transactions on the console
DUMP transactions;
导出代码
以下代码说明了在 HBase 表中存储 Pig 关系的内容:
/*
Load the transactions dataset using PigStorage into the relation transactions
*/
transactions = LOAD '/user/cloudera/pdp/datasets/hbase/transactions.csv' USING PigStorage( ',' ) AS (
listing_id: chararray,
transaction_date: chararray,
customer_id: int,
age: chararray,
residence_area: chararray,
product_subclass: int,
product_id: long,
amount: int,
asset: int,
sales_price: int);
/*
* Some processing logic goes here which is deliberately left out to improve readability
*/
/*
Use HBaseStorage to store data from the Pig relation transactions into a HBase table hbase://retail_transactions.
The individual contents of transactions are mapped to three column families transaction_details, product_details and customer_details.
*/
STORE transactions INTO 'hbase://retail_transactions' USING org.apache.pig.backend.hadoop.hbase.HBaseStorage('transaction_details:transaction_date customer_details:customer_id customer_details:age customer_details:residence_area product_details:product_subclass product_details:product_id product_details:amount product_details:asset product_details:sales_price');
结果
由于应用了糖化血红蛋白的数据摄入模式,糖化血红蛋白表中以列族和对应列表示的数据会以 PIG 的关系加载。在这个设计模式中,加载到 Pig 关系中的结果类型根据传递的参数而变化。如果用列族和列标识符(CFName:CName)指定一列,结果类型将是由标量值组成的元组。如果使用列族名和部分列名后跟星号(CFName:CN*)来指定列,则生成的列类型将是列描述符作为键的映射。
需要注意的是,在检索 HBase 中存储的时间序列或基于事件的数据时,不能使用 Pig 获取 HBase 值的时间戳信息。
作为应用 HBase 数据输出模式的结果,pig 关系中的数据存储在 HBase 表中,并映射到相应的列族和相应的列。
附加信息
本节的完整代码和数据集位于以下 GitHub 目录中:
chapter2/code/chapter2/datasets/
结构化数据的入口和出口模式
下面部分以 Hive 为例,作为我们可以获取结构化数据的来源之一,讨论不同的方法。选择 Hive 来说明结构化数据的摄入模式,因为它是企业中使用最广泛的数据接收器。此外,通过理解这种模式,您可以将其扩展到其他结构化数据。
Hive 的接入方式
Hive 摄取模式描述了如何用 Pig Latin 将数据从 Hive 表摄取和排出到 Hadoop 文件系统,以便在数据管道上进一步处理。
我们将讨论 Hive 和企业之间的相关性,并了解内部存储的各种方式(RCFile、序列文件等)。)和 Hive 数据的外部访问(HQL 和 Pig/MapReduce)。您将探索将 Hive 数据与 Pig 相结合的用例。您还将了解 Pig 如何通过提供现成的函数来更容易地摄取 Hive 数据,然后了解 Hadoop 生态系统的一个组件 HCatalog 的作用,以简化 Pig 和 Hive 表之间的连接和访问机制。
下面关于这个模式的实现级细节的讨论旨在让您熟悉重要的概念和适用的替代方案。一个示例代码片段用于从 Pig 语言的角度更好地理解模式,然后是使用模式的结果。
背景
Hive 让熟悉 SQL 并在 RDBMS 工作过的程序员很容易开发出 Hadoop。Hive 使用 HDFS 作为数据的物理存储,这从逻辑角度给出了表级抽象。Hive 实现了自己的类似 SQL 的方言 HiveQL 来访问和操作数据。HiveQL 提供了 SELECT、GROUP 和 JOIN 等运算符,这些运算符在 Hadoop 集群上执行之前会转换为 MapReduce。
在企业中,Hive 已经被数据仓库、商业智能分析、仪表盘等用例广泛认可。所有这些用例在 Hive 中都有一个公共的数据线程,它已经被清理、正确标记、键入并整齐地组织在表中,因此任何特殊的查询或报告都可以毫不费力地生成。与这种情况形成对比的是,Pig 的用例必须处理来自不同来源的新生成的数据,这种情况令人困惑,没有相关的名称、类别或元数据来解释。因此,Pig 在研究数据本身时的相关性是创建一个快速原型,并在非模态数据的表面随机性中寻找意义。
在 HDFS,Hive 数据的存储是通过将 Hive 表的内容序列化为可以存储在 HDFS 的物理文件来实现的。在 Hive 的上下文中,HDFS 被用来提供高可用性、容错性以及在 Hive 的特定文件上运行 MapReduce 的功能。目前,Hive 支持四种不同的存储文件:纯文本文件、二进制序列文件、ORC 文件和 RC 文件。这些文件格式中的每一种都有自己相关的序列化和反序列化功能,它将存储在 Hive 中的数据的表级抽象转换为存储在 HDFS 的文件。
Hive 将有关物理文件内容的信息存储在 RDBMS 上实现的外部元数据存储中(默认情况下选择 Derby、MySQL)。这个元数据存储包含了所有的信息,比如表、模式、类型、物理文件映射等。每当用户执行数据操作时,他们将首先查询这个元存储来找到数据的位置,然后访问实际的数据。
动机
Hive 以随时可用的格式存储数据,以便进行特别分析和报告。数据摄取模式与 Hive 数据相关,Hive 数据被摄取并与 Pig 数据管道中新到达的数据整合;然后,对来自 Hive 和 Pig 的组合数据进行总结、归纳和转换,以便在高级分析模型中进一步使用。
数据导出模式适用于 Pig 数据管道中已经存在的数据,有一种方法可以直接存储在 Hive 表中。
外部 Hadoop 生态系统组件(如 Pig、HBase 或 MapReduce)可以通过知道在 HDFS 使用哪种存储格式(文本、RCFile 或序列文件)来存储 Hive 数据,以及元存储中的表和模式的元数据信息来访问 Hive 数据。
这个入口和出口设计模式描述了用 Pig 读写 Hive 数据的方法。
注
与 HBase 类似,我们已经在 HDFS 加载了 Hive 文件。这与 MongoDB 形成对比,在 MongoDB 中,我们直接从外部源而不是 HDFS 读取数据。
用例
Hive 摄入设计模式的主要用例是为 Pig 提供对 Hive 中存储的数据的访问。Pig 使用这些数据的原因如下:
- 它与其他非结构化来源相集成。
- 清理并转换组合数据。
- 使用 Pig 管道中其他数据源的组合进行聚合和汇总。
Hive 导出设计模式的主要用例是提供一种机制,用于在 Hive 表的 Pig 管道中存储转换数据。您可以考虑将这种设计模式用于以下目的:
- 数据在 Pig 数据管道中与外部数据集成,然后导出到 Hive。
- 将清理和转换后的数据从 Pig 数据管道导出到 Hive。
- 将聚合导出到 Hive 或其他下游系统,以便进一步处理或分析。
模式实现
以下部分描述了 Hive 进入模式的模式实现,随后是 Hive 退出:
进入实施
以下是将 Hive 数据加载到 Pig 拉丁关系中的两种方式:
- 一种方法是显式指定反序列化程序从 Hive 中检索数据。例如
HiveColumnarLoader是 Pig 的反序列化器,专用于使用 RCFile 格式加载或序列化到 Hive 中的数据。同样,我们可以使用 Piggybank 的SequenceFileLoader从 Hive 加载已经以SequenceFile格式存储的数据。这两个例子与文件的位置、用于存储它们的模式的格式、是否使用压缩等密切相关。 - 第二种方法是使用 HCatalog 的功能将 Hive 数据加载到 Pig 中。与前一点相比,这个过程有很多优点。HCatalog 提供了一种抽象的方式来查看文件的存储。它包装了来自 HDFS 的 metastore 和存储信息,为访问表提供了统一的视角。使用 HCatalog,您不再需要担心文件的存储位置、模式的格式或是否使用压缩。您只需要指定 HCatalog 加载器的表名,它就可以在幕后完成必要的管道工作,并绘制底层的存储格式、位置和模式。现在用户不知道表的位置、分区、模式、压缩类型和存储格式。HCatalog 通过表级抽象简化了这一点,并在幕后做了大量工作。
出口变现
导出设计模式是使用 HCatalog 函数实现的,该函数将 Pig 关系中的数据存储到 Hive 表中。HCatalog 提供了一个 HCatStorer 接口,将 Pig 关系的内容存储到 HCatalog 管理的 Hive 表中。有关为什么 HCatalog 接口是加载和存储操作的最佳选择的更多信息,请参考上一节入口实现中的第二点。
下图说明了这些设计模式遵循的方法:
Hive 和 PIG 的结合
代码片段
下面的代码示例使用了一个零售交易数据集样本。包含 T0、T1、T2、T3、T4、T5、T6、T7、T8 等属性。这个数据已经存储在 Hive 中来说明这个例子。Hive 的本地存储 RCFile,包含此表的内容,用于解释直接访问;HCatalogLoader在下例中也有说明。
进入码
下面的代码说明了从 Hive 获取数据。
使用 RCFile 导入数据
下面的代码说明了HiveColumnarLoader从存储在 RCFile 中的 Hive 表加载数据的用法:
/*
Register the Piggybank jar file to be able to use the UDFs in it
*/
REGISTER '/usr/share/pig/contrib/piggybank/java/piggybank.jar';
-- Register Hive common and exec jars
REGISTER '/usr/lib/hive/lib/hive-common-0.11.0.1.3.0.0-107.jar';
REGISTER '/usr/lib/hive/lib/hive-exec-0.11.0.1.3.0.0-107.jar';
/*
Load retail_transactions_rc RCfile and specify the names of the columns of the table and their types in the constructor of HiveColumnarLoader.
*/
transactions = LOAD '/apps/hive/warehouse/transactions_db.db/retail_transactions_rc' USING org.apache.pig.piggybank.storage.HiveColumnarLoader('transaction_no int,transaction_date string,cust_no int,amount double,category string,product string,city string,state string,spendby string');
/*
* Some processing logic goes here which is deliberately left out to improve readability
*/
/*
Display the contents of the relation transactions on the console
*/
DUMP transactions;
使用 HCatalog 导入数据
下面的代码展示了如何使用 HCatalog 从 Hive 加载数据:
/*
Specify the table name as the input to the HCatLoader function provided by HCatalog.
This function abstracts the storage location, files type, schema from the user and takes only the table name as input
*/
transactions = LOAD 'transactions_db.retail_transactions' USING org.apache.hcatalog.pig.HCatLoader();
/*
* Some processing logic goes here which is deliberately left out to improve readability
*/
/*
Display the contents of the relation transactions on the console
*/
DUMP transactions;
导出代码
下面的代码展示了如何使用 HCATTOR 将数据导出到 Hive:
-- Register piggybank and hcatalog-pig-adapter jars
REGISTER '/usr/share/pig/contrib/piggybank/java/piggybank.jar';
REGISTER '/usr/lib/hcatalog/share/hcatalog/hcatalog-pig-adapter.jar';
/*
Load the transactions dataset into the relation transactions
*/
transactions = LOAD '/user/cloudera/pdp/datasets/hive/retail_transactions.csv' USING org.apache.pig.piggybank.storage.CSVLoader() AS (transaction_no:int, transaction_date:chararray, cust_no:int, amount:double, category:chararray, product:chararray, city:chararray, state:chararray, spendby:chararray);
/*
* Some processing logic goes here which is deliberately left out to improve readability
*/
/*
Specify the Hive table name transactions_db.retail_transactions as the input to the HCatStorer function.
The contents of the relation transactions are stored into the Hive table.
*/
STORE transactions INTO 'transactions_db.retail_transactions' using org.apache.hcatalog.pig.HCatStorer();
结果
应用进气设计模式后,Hive 表中的数据以 Pig 关系加载,并准备进一步处理。使用HCatLoader时,正确解释 HCatalog 的数据类型如何映射到 Pig 类型很重要。除了 HCatalog 中映射到二进制的bytearray类型外,所有基本类型的 PIG 都映射到它们对应的 HCatalog 类型。在复杂数据类型中,HCatalog 的映射映射到 Pig 中的映射,HCatalog 的列表映射到 Pig 中的包,HCatalog 的struct映射到 Pig 中的元组。
应用导出设计模式,Pig 关系中的数据存储在 Hive 表中,以便在 Hive 中进行报告和具体分析。前段提到的HCatLoader的所有模式转换规则也适用于HCatStorer。HCatStorer类接受代表分区表键值对的字符串参数。如果要在分区表中存储 Pig 关系的内容,应该强制指定这个参数。
附加信息
- http://pig .Apache。组织/文档/r 0 .11.0/API/org/Apache/pig ybbank/storage/hivecolumnarloader .html
- https://cwiki。 Apache. Organize/gather/show/hive /HCatalog+ load storage
本节的完整代码和数据集位于以下 GitHub 目录中:
chapter2/code/chapter2/datasets/
半结构化数据的导入导出模式
本节描述半结构化数据的设计模式,如 XML、JSON 和大型机数据。我们选择了 XML 和 JSON,因为它们是互联网数据交换最流行的编码格式。大量数据被锁定在文档、期刊和内容管理系统中,这可能会从分析中受益。之所以选择大型机数据作为这个用例,主要是因为它在很多企业中是一个相对未被探索的领域,随着新模型的出现,它最终可能会被普及。
主机摄入模式
大型机摄取模式描述了如何使用 Pig Latin 将从大型机导出的数据摄取到 Hadoop 文件系统中,以便在数据管道上进一步处理。
我们将讨论处理存储在大型机中的数据与企业之间的相关性,并对大型机内部存储和访问数据的各种方式有更深入的了解。我们还将结合 Pig 讨论摄取的动机和大型机数据的用例。您还将学习 Pig 如何比使用用 Java 编写的 MapReduce 代码(使用 UDFs)更直观地获取数据。
下面关于这个模式的实现级细节的讨论旨在让您熟悉重要的概念和适用的替代方案。一个示例代码片段用于从 Pig 语言的角度更好地理解模式,然后是使用模式的结果。
背景
大型机似乎还有很长的路要走,很难想象一个没有这些老黄牛来处理这些事务几十年的世界。这就是这些机器的稳定性。即使在极高的数据吞吐量下,它们也能忠实地运行,一秒钟也不闪烁。难怪这些工程奇迹已经成为从飞机和汽车到金融服务和政府的商业支柱,多年来不断销售、跟踪、插入和更新这些实体的每一笔交易。
凭借 20 世纪 60 年代推动工业革命的经验,大型机随着时间的推移而发展,变得更加强大,并且能够处理它们设计的特定高吞吐量事务性工作负载。如今,他们使用定制的处理器和其他高端硬件来实施虚拟化、纵向扩展并展示事务完整性,尽管吞吐量极高。显然,大型机可以提供比任何其他体系结构更好的结果,具有极高的吞吐量、难以置信的高可用性、可靠性和顶级安全性。
动机
Hadoop 在从大型机卸载大量事务数据并对其进行批处理方面发挥着越来越重要的作用。这与通过将处理从昂贵的定制系统转移到包含 Hadoop 框架的商业硬件来提高大型机的事务吞吐量和批处理时间是一致的。同样,当大型机的批处理能力无法有效扩展时(在一个价位和性能范围内),将处理工作卸载给 Hadoop 是有好处的,因为 Hadoop 可以以更好的性价比完成这项工作。如下图所示:
批处理和卸载到 Hadoop
用例
这个设计模式可以应用于解决以下用例:
- 将数据从大型机迁移到 Pig,以与其他系统的数据集成并创建高级分析。
- 将非关键批次工作负载卸载到 Pig,大幅释放大型机吞吐量。
- 在 Pig 中重写 COBOL 代码带来了可重用性、可维护性、简单性和紧凑性的优点。
模式实现
通过卸载,Hadoop 的相关处理意味着将 COBOL 编写的代码重写到 MapReduce,并从大型机传输数据。
COBOL 是通用语言,用于大型机访问 DB2 和其他数据库,执行批处理和处理在线事务。不适合在互联网上实现复杂的算法,可能有利于更新业务需求,如风险建模、预测分析等。
为了将 COBOL 代码迁移到 MapReduce,我们可以选择一些在大型机中实现的函数,这些函数可以遵循 mapper 和 Reduce 的结构。例如,遗留的 COBOL 代码可以对数十亿条记录进行排序,将它们与其他数据源进行合并和分组,并执行复杂的转换,这比 Pig 中的 COBOL 更有效。在 Pig 代码中加入 Java UDF 函数,可以对数据管道进行高级分析;这种结合可能会创造奇迹。因此,将代码迁移到 Pig Latin 以有效地执行特定的处理可以带来丰厚的回报。
迁移大型机数据有其自身的一系列挑战。通常,大型机在内部将各种类型的数据存储在 VSAM 文件、平面文件和数据库管理系统中。对于 Hadoop 来说,要访问这些数据,需要将其转换成它能理解的格式,然后通过文件传输机制物理传输到 Hadoop 集群。使用特定的实用程序(如 IDCAMS),您可以将 VSAM 文件转换为平面文件供 Hadoop 使用。
每个大型数据库管理系统都有自己的专用工具,可以了解数据库管理系统的内部文件存储格式,并将其转换为平面文件。我们可能需要处理这些平面文件从大型机中的一个代码页到 Hadoop 集群的目标机器中的另一个代码页的转换。一般来说,从主机导出的平面文件是反规格化的 CSV 格式。如下图所示:
大型机数据提取和摄取到 Hadoop 中
为了理解 CSV 格式每一列的物理布局和定义,使用了一个专用于大型机的字帖。在 Hadoop 中,字帖提供的信息被用作分析 CSV 和解码 CSV 文件含义的模式。因此,主机数据的摄取需要两个输入:一个是平面文件本身,另一个是字帖。
Pig 有内置的加载器,可以读取 CSV 文件,但是解析必须在 CSV 上用字帖的内容完成。因此,必须编写一个 Java UDF 或自定义加载器来实现这一点。
代码片段
下面的代码示例使用了一个数据集,该数据集包含从大型机到 CSV 文件的与车辆维修索赔相关的示例车辆保险索赔数据。VSAM 文件中数据元素的元数据和物理布局在字帖中定义。字帖包含claim、policy、vehicle、customer,、garage details等字段。下一节中的 Java 代码片段解析字帖,检索元数据,并使用它将数据加载到 CSV 文件中。
以下 Pig 脚本使用自定义加载器将从大型机提取的数据加载到 CSV 文件中。这里VSAMLoader使用字帖文件确定 CSV 文件的元数据并加载:
/*
Register custom UDF vsamloader.jar and cb2java jar which is a dynamic COBOL copybook parser for Java
*/
REGISTER '/home/cloudera/pdp/jars/vsamloader.jar';
REGISTER '/home/cloudera/pdp/jars/cb2java0.3.1.jar';
/*
Load the contents of the automobile insurance claims dataset using custom UDF.
VSAMLoader uses the copybook file to parse the data and returns the schema to be used to load the data
*/
data = LOAD '/user/cloudera/pdp/datasets/vsam/automobile_insurance_claims_vsam.csv' USING com.mycustomloader.vsamloader.VSAMLoader();
/*
* Some processing logic goes here which is deliberately left out to improve readability
*/
-- Display the contents of the relation data on the console
DUMP data;
-- Display the schema of the relation data
DESCRIBE data;
以下是 VSAMLoader 的 Java 代码片段,这是一个自定义的加载器实现:
@Override
public ResourceSchema getSchema(String arg0, Job arg1) throws IOException {
.
.
while (it.hasNext()) {
Map.Entry pairs = (Map.Entry) it.next();
//Get the next key/value pairs
String key = (String) pairs.getKey();
String value = (String) pairs.getValue();
/*For Group and Alphanumeric types in copybook, return
pig compliant type chararray*/
if (value.toString()
.equals("class net.sf.cb2java.copybook.Group")
|| value.toString().equals("class net.sf.cb2java.copybook.AlphaNumeric")){
fieldSchemaList.add(new FieldSchema(key,
org.apache.pig.data.DataType.CHARARRAY));
}
/*For Decimal type in copybook, return
pig compliant type integer*/
else if (value.toString()
.equals("class net.sf.cb2java.copybook.Decimal")){
fieldSchemaList.add(new FieldSchema(key,
org.apache.pig.data.DataType.INTEGER));
}
// Else return default bytearray
else
{
fieldSchemaList.add(new FieldSchema(key,
org.apache.pig.data.DataType.BYTEARRAY));
}
}
return new ResourceSchema(new Schema(fieldSchemaList));
}
在vsamloader JAR 实现的自定义加载器代码中,我们使用外部 API 解析字帖文件,得到所有的值。然后,我们从 Pig API 及其getSchema()方法中实现一个名为LoadMetaData的接口,它将返回我们通过解析字帖获得的模式。使用类型为FieldSchema的ArrayList类,它将最终在字帖文件中填写列名及其数据类型。这个ArrayList作为新模式返回,小 PIG 加载 VSAM 文件时会用到。
结果
将该模式应用于主机数据提取的结果是将平面文件中的数据加载到 Pig 拉丁关系中进行进一步处理。因为 Pig 中没有现成的函数来理解字帖格式,所以我们通过自定义加载器来扩展 Pig。必须注意在自定义加载器中正确映射模式,因为并非所有的 COBOL 数据类型都可以轻松映射到 Java 对应类型。例如,COBOL 对布尔值和日期类型的支持是有限的,所以我们必须实现一个特殊的转换来用 Java 处理它以获得准确的结果。有关更多信息,请参见下一节中的链接。
附加信息
- http://pig。 Apache. Organization/document /r 0. 11 .1 UDF。 Html # Load-Store-Function
- pic.dhe.ibm.com/infocenter/…
- http://www .3480-3590-数据转换 com/article-reading-cobol-layout-1 .html
本节的完整代码和数据集位于以下 GitHub 目录中:
chapter2/code/chapter2/datasets/
XML 接收输出模式
本节介绍如何使用 Pig Latin 将 XML 编码的文档或日志的内容导入和导出到 Hadoop 文件系统,以便在数据管道上进一步处理。
我们将讨论如何处理存储在 XML 中的数据与企业的相关性,了解 Pig 访问 XML 数据(原始 XML 和二进制)的各种方式。您将了解使用原始和二进制 XML 解析的优缺点,然后了解将 XML 数据与 Pig 相结合的动机和用例。您还将学习 Pig 如何比使用用 Java 编写的 MapReduce 代码更直观、更高效地获取数据。
下面关于这个模式的实现级细节的讨论旨在让您熟悉重要的概念和适用的替代方案。一个示例代码片段用于从 Pig 语言的角度更好地理解模式,然后是使用模式的结果。
背景
XML 是以直观的方式存储和传输数据的最广泛使用的协议之一,这使得人类和机器相对容易理解数据的含义。XML 是文本格式,不是二进制格式。它具有用相关元数据编码数据的特殊能力,并且可以自己阐明其含义。由于这一特性,XML 已经成为大多数互联网应用事实上的数据传输标准。XML 的通用性在于它不仅可以表示文档,还可以表示网络服务中任意的数据结构。今天,我们看到数以千计的基于 XML 的分类法、信息交换格式和文档格式——如微软 Office、SOAP、RSS、XHTML 和 ATOM——正在被广泛使用。从分析的角度来看,所有这些基于 XML 的数据存储和传输格式都包含了丰富的信息。
动机
使用 Hadoop 接收和输出 XML 本来就很复杂,在灵活性上也有一些妥协。复杂性来自于任意的嵌套,元数据本身所需要的空间可能是惊人的。尽管 XML 通过包含标签和其他可选字段为您提供了模拟现实世界的灵活性,并使用大量元数据信息对数据进行编码,但它显然会导致属性的深度嵌套,并使大量数据的计算更加复杂和耗时。这意味着将 XML 文档加载到计算机内存中是一项非常复杂的 CPU 密集型工作。
由于上述复杂性,Hadoop 提供了许多优势来更快地处理大型复杂的 XML 数据,并且通过接收、转换和导出 XML 供下游系统进一步使用,它可以使用更低成本的操作。要在 Hadoop 中处理 XML,您可能必须考虑处理 XML 数据的性质和上下文。
摄取原始 XML 的动机
Hadoop 中摄取和处理 XML 的一个原因是当你事先不知道 XML 模式,在读取文件时想要理解它。该方法的要点如下:
- XML 数据以其原始格式加载,在查询过程中找到其模式,并在发现后执行其转换。
- 这种方法本质上更具探索性;它提供了快速的初始加载,因为数据没有使用序列化以二进制格式进行清理或存储。
- 它支持更大的灵活性,因此可以使用多个模式来解析不同类型分析查询的 XML。
- 它适用于定义良好的格式,这可能会导致为每个查询解析 XML 数据,并对查询性能产生轻微影响。
摄取二进制 XML 的动机
在 Hadoop 中摄取和处理 XML 的另一个原因是当您已经知道了 XML 的模式,并且想要对 XML 执行高性能查询时。该方法的要点如下:
- XML 必须首先被解析,以二进制格式序列化到磁盘,跨节点拆分,压缩,并针对查询进行优化。
- 如果在加载过程中需要大量的清理和重新格式化,这种方法是可行的。
- 如果需要对生产工作负载执行重复查询,这是合适的。
- 如果加载时模式未知,则此方法不适合,因为以可查询格式加载、预处理和存储 XML 需要很长时间。
XML 输出的动机
Hadoop 可用于从 HDFS 的 CSV 和 Hive 表等结构化数据创建和输出 XML 文件。XML 文件也可以直接摄取到 Hadoop 中,这样就可以由 Pig 进行验证或转换,写回 XML,满足下游系统的交换格式。
用例
XML 摄取模式可用于以下用例,以解决以下问题:
- 它可用于从内容管理系统(如技术文档、参考手册和期刊)接收基于 XML 的文档数据。摄取是在使用 Lucene 创建搜索索引并对其执行分析之前完成的。
- 它可以用来接收包含 SOAP 和 EDXL-CAP 类型的消息文本的 XML 日志,并分析系统之间的请求和响应。例如,可以从网络故障管理系统中提取 XML 编码的消息,并对其进行分析,以了解或预测子系统未来的故障。
当 HDFS 的结构化数据(分离的平面文件或配置单元表)需要转换为可扩展标记语言进行处理和序列化时,可以使用可扩展标记语言导出模式,以便上游系统可以使用可扩展标记语言进一步处理数据。
模式实现
Pig 提供结构直接加载原 XML 文件,支持加载预处理后的 XML 文件。
XML 原始摄取的实现
pigybank 库提供XMLLoader功能访问 XML 文件的内容。XMLLoader该函数的参数是一个内部转换成单记录元组的 XML 标记名。该记录包含开始 XML 标记和结束 XML 标记中包含的文本。使用从 XML 文件返回的元组,您可能必须执行进一步的解析,以将记录级 XML 值分解为它们的组件值;一般使用正则表达式函数REGEX_EXTRACT进行展平投影。
XML 二进制摄取的实现
将 XML 转换为二进制格式进行拆分是一个两步的过程。
- 第一步,为了解析 XML 文档,可以将文件完全读入基于内存的数据结构,使用 DOM 等解析器可以随机访问数据的所有元素。或者,您可以连续访问文件的内容,并一次控制一个解析步骤。这可以通过 XML SAX 解析器来完成,并且执行速度稍慢。DOM 解析的优点是可以链接多个处理器,但是编程比较困难,而 SAX 解析的优点是容易编程和拆分。但是,另一方面,SAX 执行起来很慢,因为它是一种用于解析 XML 文档的串行访问机制。
- 第二步,将解析后的 XML 转换成 Hadoop 可以处理的可拆分二进制格式,Avro 是执行符合这些标准的序列化的最佳选择,这有助于将 XML 文档转换成字节流,并以磁盘格式存储。Avro 是专门为 Hadoop 设计的,使其成为一种高度可压缩和可分离的二进制格式,与序列文件非常相似。与序列文件不同,只能通过 Java API 访问,Avro 文件可以从 C、C++、C#、Ruby、Python 等其他语言访问。凭借其独特的互操作性格式,Avro 文件可以从一种语言编写的代码传输到另一种语言编写的不同代码,甚至可以从 C 语言等编译语言传输到 Pig 等脚本语言。
- 每个 Avro 文件都用元数据包装了 XML 文件的底层内容,元数据包含反序列化或读取内容所需的信息。Avro 将元数据与文件的实际内容一起存储在文件中,这使得其他程序更容易首先理解元数据,然后处理嵌入的数据。一般元数据以 JSON 格式存储,数据以二进制格式存储。
- Avro 文件还包括一个标签,用于在集群的多个节点上划分数据。在访问序列化的 Avro 文件之前,您必须将 XML 文件准备成 Avro 格式,并使用 piggybank 的
AvroStorage将其读入 Pig 拉丁语的关系。
下图描述了上述实现方面:
XML 数据的进入和退出
代码片段
下面的代码示例使用了一个包含 MedlinePlus 健康讨论的 XML 数据集。
【T0】XML 原始摄取代码
XML 数据由数据元素的标签组成,如主题标题、相关网站、主要语言、日期、词汇、摘要、成员资格等其他语言的相关健康主题和内容。下面的代码片段解析 XML 标记,并将内容作为关系加载到 Pig 拉丁脚本中:
-- Register piggybank jar
REGISTER '/home/cloudera/pig-0.11.0/contrib/piggybank/java/piggybank.jar';
/*
XMLLoader accesses the specified XML file and retrieves the record level value to be stored in the tuple data specified by the parameter to the XMLLoader.
*/
data = LOAD '/user/cloudera/pdp/datasets/xml/mplus_topics_2013-09-26.xml' USING org.apache.pig.piggybank.storage.XMLLoader('article');
/*
* Some processing logic goes here which is deliberately left out to improve readability
*/
/*
Print the contents of the relation data to the console
*/
DUMP data;
【T0】XML 二进制摄取代码
以下代码执行 XML 的二进制摄取:
-- Register piggybank jar
REGISTER '/usr/share/pig/contrib/piggybank/java/piggybank.jar';
-- Register Avro and JSON jar files
REGISTER '/home/cloudera/pdp/jars/avro-1.7.4.jar';
REGISTER '/home/cloudera/pdp/jars/json-simple-1.1.1.jar';
/*
Assign the alias AvroStorage to piggybank's AvroStorage UDF
*/
DEFINE AvroStorage org.apache.pig.piggybank.storage.avro.AvroStorage();
/*
Load the dataset using the alias AvroStorage into the relation health_topics
*/
health_topics = LOAD '/user/cloudera/pdp/datasets/xml/mplus-topics_2013-09-26.avro' USING AvroStorage;
/*
* Some processing logic goes here which is deliberately left out to improve readability
*/
-- Print the contents of the relation health_topics to the console
DUMP health_topics;
下图描述了将 XML 文件转换为 AVRO 所涉及的步骤:
XML 到 Avro 预处理
我们使用第三方工具从给定的 XML 文件生成 XSD,并使用 schemagen 生成 JAXB、Avro 绑定和 Avro 模式。在内部,schemagen 使用 JAXB 绑定编译器 XJC;;然后,它从 XSD 模式文件生成一个代码模型。然后执行 XJC 插件以 JSON 格式创建 Avro 模式。XJC 插件调用 Avro 的 Java 模式编译器来生成新的 Java 类,以便序列化到 Avro 和从 Avro 序列化。
【T0】XML 导出代码
以下是将 CSV 文件内容转换为 XML 格式的 Pig 脚本。
PIG
自定义存储功能 XMLStorage 用于完成 CSV 文件内容到 XML 格式的转换:
/*
Register custom UDF jar that has a custom storage function XMLStorage to store the data into XML file.
*/
REGISTER '/home/cloudera/pdp/jars/xmlgenerator.jar';
/*
Load the transactions dataset using PigStorage into the relation transactions
*/
transactions = LOAD '/user/cloudera/pdp/datasets/hbase/transactions.csv' USING PigStorage( ',' ) AS (
listing_id: chararray,
transaction_date: chararray,
customer_id: int,
age: chararray,
residence_area: chararray,
product_subclass: int,
product_id: long,
amount: int,
asset: int,
sales_price: int);
/*
* Some processing logic goes here which is deliberately left out to improve readability
*/
/*
Custom UDF XMLStorage generates the XML file and stores it in the xml folder
*/
STORE transactions INTO '/user/cloudera/pdp/output/xml' USING com.xmlgenerator.XMLStorage();
【T0】XML 存储
以下是 XML 存储的代码:
protected void write(Tuple tuple)
{
// Retrieving all fieds from the schema
ResourceFieldSchema[] fields = schema.getFields();
//Retrieve values from tuple
List<Object> values = tuple.getAll();
/*creating xml element by using fields as element tag
and tuple value as element value*/
Element transactionElement =
xmlDoc.createElement(XMLStorage.elementName);
for(int counter=0;counter<fields.length;counter++)
{
//Retrieving element value from value
String columnValue =
String.valueOf(values.get(counter));
//Creating element tag from fields
Element columnName =
xmlDoc.createElement(fields[counter].getName().toString().trim());
//Appending value to element tag
columnName.appendChild
(xmlDoc.createTextNode(columnValue));
//Appending element to transaction element
transactionElement.appendChild(columnName);
}
//Appending transaction element to root element
rootElement.appendChild(transactionElement);
}
write该方法以元组为输入,表示 CSV 文件中的一行。此方法为元组中的每个字段创建一个 XML 元素。对 CSV 中的所有行重复此过程,以生成一个 XML 文件。
结果
将此模式应用于 medline XML 文件的结果是将数据加载到 Pig Latin 关系中进行进一步处理。请确保 XML 文件格式正确,所有元素都有开始和结束标记,否则XMLLoader可能会返回无效值。
应用导出设计模式,关系事务中的数据被写入指定路径的 XML 文件中。
附加信息
- http://pig .Apache。组织/文档/r 0 .11.0/API/org/Apache/PIG 库/仓储/xmlloader .html
- http://pig .Apache。组织/文档/r 0 .11 . 0/API/org/Apache/pig/pig bank/storage/avro/avrostorage .html
本节的完整代码和数据集位于以下 GitHub 目录中:
chapter2/code/chapter2/datasets/
JSON 进入退出模式
JSON 摄取模式描述了如何从 Hadoop 文件系统中通过 Pig Latin 摄取并输出表示为 JSON 的数据,从而进一步处理数据管道中的数据。
我们将讨论如何处理 JSON 中存储的数据与企业的相关性,并了解可以使用 Pig 访问和存储 JSON 数据的各种方式(简单 JSON 和嵌套 JSON)。您将了解使用简单 JSON 和嵌套 JSON 解析的优缺点,了解将 JSON 数据与 Pig 相结合的动机和用例。您还将学习 Pig 如何比用 Java 编写的 MapReduce 代码更直观地摄取这些数据(通过使用象鸟等外部库)。
下面关于这个模式的实现级细节的讨论旨在让您熟悉重要的概念和替代方案(如果适用的话)。一个示例代码片段用于从 Pig 语言的角度更好地理解模式,然后是使用模式的结果。
背景
JSON 是构造文本的另一种方式。JSON 是一种数据交换格式,它以分层的方式描述数据,这样机器和人类都可以读取数据并对其进行操作。
JSON 以一种简单得多的方式表示数据,更像是一个键值对,其中的值可以是非常原始的,比如整数、字符串和数组。JSON 不支持像 XML 这样极其复杂和嵌套的数据类型。它不太冗长,只需要一个查找函数来检索值,因为数据存储在键值对中。这使得 JSON 非常紧凑,适合更有效地表示数据,不像 XML。在 XML 中,数据以复杂的嵌套方式由丰富的数据类型表示,这使得解析 XML 树变得非常复杂。在现实世界中,JSON 用于存储简单的数据类型,而 XML 用于建模数据类型的复杂性,这提供了一些功能,使您能够更好地表达数据的结构。
动机
JSON 作为最受欢迎的数据表示标准之一的崛起,很大程度上是由于社交网络公司的强劲崛起,如领英、推特和脸书。这些企业和许多其他需要与外部世界交换内部业务数据(如社交对话或任何占用空间较小的数据)的公司主要转向能够在不增加 XML 复杂性的情况下承载简单高效负载的 API。JSON 是这些 API 的首选格式,因为它的简单性和作为关键数据源的实现使得解析变得容易。
随着社交媒体的兴起,我们可以看到 NoSQL 数据库的出现,这使得 JSON 成为他们的支柱。许多这样的数据库,如 MongoDB、CouchDB 和 Riak,都使用 JSON 作为它们的主要存储格式。由于 JSON 的使用,这些数据库表现出极高的性能特点和横向扩展的能力。这些数据库是专门为互联网规模的应用而设计的,其中实时响应的需求是最重要的。
以非社交媒体为中心的企业也在加速传播。目前,JSON 用于存储具有多个标题和其他键值对的日志文件。JSON 格式的日志数据很好地表示了用户会话和用户活动,每个用户活动的信息都嵌套在会话信息下。这种 JSON 格式的数据嵌套在执行高级分析时提供了天然的优势。对于处理传感器数据的企业来说,JSON 也是一个很好的选择,传感器数据包含为不同测量收集的各种属性。
虽然 JSON 作为快速检索和更高效承载互联网有效载荷的首选存储格式表现良好,但在很多用例(如日志处理、传感器分析)中,JSON 中表示的数据不仅用于搜索,还广泛集成其他企业数据资产进行分析。这种集成意味着对 JSON 和其他结构化数据的组合进行批处理。下面几节讨论的接收设计模式描述了将 JSON 接收到数据管道中的方法。
批处理数据管道的输出有时可以概括为 JSON 表示的现成数据。这适用于使用 JSON 将批处理 JSON 输出馈送到 NoSQL 数据库的用例,以及 JSON 可以用作 web 服务的负载的用例。导出设计模式展示了我们如何使用 Pig 将数据管道中存储的数据转换为 JSON 格式。
用例
以下是 Pig 摄取和输出 JSON 数据的用例:
- 使用摄取设计模式将 JSON 数据集成到 Pig 关系中,以便数据管道中的组合数据可以用于分析。
- 使用摄取设计模式来消费来自 Twitter 和其他社交媒体来源的 JSON 应用编程接口,以执行高级分析,例如情感挖掘。
- 存储在 JSON 中的传感器数据是使用机器故障分析的捕获设计模式捕获的。
- 使用导出设计模式以 JSON 格式存储 HDFS 现有平面文件的内容。这种模式对于以 JSON 格式存储复杂数据集成或转换管道的结果以供下游系统访问也很有用。
模式实现
下面部分展示了出入口的实现。
进入实施
JSON 可以通过JSONLoader函数加载到 Pig 关系中,将 JSON 文件的内容加载到地图中。JSONLoader该功能可以使用或不使用模式信息。
- 如果在
JSONLoader中提供了模式信息,那么 Pig 和 JSON 数据类型之间的映射是直接的,并且遵循指定的模式。 - 当
JSONLoader中没有提供模式信息时,Pig 关系的数据类型设置为默认bytearray,在执行周期的后期推断实际模式。要处理一个大的 JSON 文件并对其执行并行处理,您可能必须用每行一个 JSON 对象格式来格式化 JSON 文件。当您需要解析超过 HDFS 存储块大小的非常大的 JSON 文件时,以及当您可以控制 JSON 的格式以每行包含一个 JSON 对象时,这个先决条件是适用的。 - 当 JSON 文件不能格式化为每行包含一个 JSON 对象时,MapReduce 无法拆分 JSON 文件,因为 JSON 是嵌套的,在不同的级别使用相同的元素。JSON 格式与 XML 形成对比,后者有一个开始和结束标记来表示嵌套数据结构的边界。这个问题的解决方案在象鸟库
LZOJSONLoader的实现中得到了解决,允许确定嵌套 JSON 文件的划分边界。大象库是一个开源的实用程序库,用于处理 JSON 和 Twitter 提供的其他格式。在github.com/kevinweil/e…有售。
出口变现
使用 JsonStorage功能,以 JSON 格式存储 PIG 关系的内容。Pig 关系的内容在输出中存储为单个 JSON 行。执行模式映射时,JsonStorage函数将 Pig 元组映射到 JSON 对象。同样,它将 Pig 映射到一个 JSON 对象,Pig 包对应于 JSON 数组。
下图描述了如何使用 Pig 摄取和排出 JSON 的总体思路:
JSON Hadoop 集成
代码片段
下面的代码示例使用了来自安然语料库的样本数据集,该数据集包含来自 150 个用户的电子邮件,平均每个用户有 757 条消息。数据集中的字段是 T0、T1、T2、T3、T4、T5、T6 和 T7。
进入码
下面的部分展示了将 JSON 格式存储的数据摄入 Pig 关系的代码及其解释。
简单 JSON 的代码
使用JsonLoader加载 JSON 文件的代码如下:
/*
Use JSONLoader UDF, it takes in the parameter of the JSON schema and loads the contents of the JSON file emails.json into a map enron_emails
*/
enron_emails = LOAD '/user/cloudera/pdp/datasets/json/emails.json' USING JsonLoader('body:chararray, from:chararray, tos:chararray, ccs:chararray, bccs:chararray, date:chararray, message_id:chararray, subject:chararray');
/*
* Some processing logic goes here which is deliberately left out to improve readability
*/
/*
Display the contents of the relation enron_emails on the console
*/
DUMP enron_emails;
重要的是注意到JsonLoader没有使用AS子句来提供模式。
嵌套 JSON 的代码
加载嵌套 JSON 的 PIG 脚本如下图,我们用象鸟库来实现:
/*
Register elephant-bird and JSON jar files
*/
REGISTER '/home/cloudera/pdp/jars/elephant-bird-core-3.0.5.jar';
REGISTER '/home/cloudera/pdp/jars/elephant-bird-pig-3.0.5.jar';
REGISTER '/home/cloudera/pdp/jars/json-simple-1.1.1.jar';
/*
Use ElephantBird's JsonLoader for loading a nested JSON file
The parameter –nestedload denotes nested loading operation
*/
emails = LOAD '/user/cloudera/pdp/datasets/json/emails.json' USING com.twitter.elephantbird.pig.load.JsonLoader('-nestedLoad');
/*
* Some processing logic goes here which is deliberately left out to improve readability
*/
/*
Display the contents of the relation emails on the console
*/
DUMP emails;
导出代码
以下部分展示了与 JSON 格式相关的 Pig 中存储的导出数据的代码及其说明:
/*
Load the JSON file using JsonLoader to the relation enron_emails
*/
enron_emails = LOAD '/user/cloudera/pdp/datasets/json/emails.json' USING JsonLoader('body:chararray, from:chararray, tos:chararray, ccs:chararray, bccs:chararray, date:chararray, message_id:chararray, subject:chararray');
/*
* Some processing logic goes here which is deliberately left out to improve readability
*/
/*
Use JsonStorage to store the contents of the relation to a json file
*/
STORE enron_emails into '/user/cloudera/pdp/output/json/output.json' USING JsonStorage();
结果
应用设计模式会导致 JSON 数据以 Pig 关系存储。如果字段解析不正确或找不到字段,JsonLoader将在 Pig 关系中存储空值。JsonLoader不关心构造函数中字段的顺序;您可以按任何顺序指定它们。JsonLoader只要字段名匹配,就可以正确解析。如果存在类型不匹配,则根据可行性进行JsonLoader自动类型转换。可以把int铸成string,但不能把string铸成int。作为最佳实践,您可以考虑使用没有模式定义的JsonLoader函数来理解 JSON 对象中所有键的顶层视图,并更好地理解数据。
应用导出设计模式将导致来自 Pig 关系的数据以 JSON 格式存储。JsonStorage功能使用缓冲技术以 JSON 格式存储。这种缓冲能力用于加载大容量数据,从而提高存储性能。您可以在JsonStorage构造函数中以千字节为单位指定固定大小的缓冲区。
附加信息
本节的完整代码和数据集位于以下 GitHub 目录中:
chapter2/code/chapter2/datasets/
总结
在本章中,我们从了解企业环境中的数据类型开始,并讨论每种数据类型的相关性、它们在企业中的使用以及 Hadoop 如何处理这些数据。
在下一节中,我们从更仔细地查看特定类型的数据开始,并将入口和出口设计模式应用于它们。我们涵盖了非结构化、结构化和半结构化类别中最相关的数据类型。我们还试图突出高级数据类型(如图像和大型机)的设计模式,以考虑 Pig 的适应性和可扩展性。在本书展示的每个设计模式中,我们从背景细节开始,了解模式的上下文相关性,然后了解模式对特定数据类型的动机和适用性。通过线程讨论了代码和模式的实现,简化了设计模式的实现。我们讨论了为什么 Pig 更好,并讨论了解决设计模式中特定情况的各种选项。
在下一章中,我们将了解更多可以应用于各种数据格式的数据分析模式。下一章的目标是让你通过分析数据,熟练运用 Pig 【T0】来理解数据的内容、脉络、结构和条件。Pig 提供了一组丰富的原语来分析数据,您将学习在分析企业级数据时使用的适当设计模式。您还将学习扩展 Pig 的功能,以适应数据分析的更高级用途。