Pig系统分析(8)-Pig可扩展性
本文是Pig系统分析系列中的最后一篇了,主要讨论怎样扩展Pig功能。不仅介绍Pig本身提供的UDFs扩展机制,还从架构上探讨Pig扩展可能性。
补充说明:前些天同事发现twitter推动的Pig On Spark项目:Spork,准备研究下。
UDFs
通过UDFs(用户自己定义函数),能够自己定义数据处理方法,扩展Pig功能。实际上,UDFS除了使用之前须要register/define外。和内置函数没什么不同。
主要的EvalFunc
以内置的ABS函数为例:
public class ABS extends EvalFunc<Double>{
/**
* java level API
* @param input expectsa single numeric value
* @return output returns a single numeric value, absolute value of the argument
*/
public Double exec(Tuple input) throws IOException {
if (input == null || input.size() == 0)
return null; Double d;
try{
d = DataType.toDouble(input.get(0));
} catch (NumberFormatException nfe){
System.err.println("Failed to process input; error -" + nfe.getMessage());
return null;
} catch (Exception e){
throw new IOException("Caught exception processing input row", e);
}
return Math.abs(d);
}
……
public Schema outputSchema(Schema input) ;
public List<FuncSpec> getArgToFuncMapping() throws FrontendException; }
- 函数都继承EvalFunc接口,泛型參数Double代表返回类型。
- exec方法:输入參数类型为元组,代表一行记录。
- outputSchema方法:用于处理输入和输出Schema
- getArgToFuncMapping:用于支持各种数据类型重载。
聚合函数
EvalFuc方法也能实现聚合函数,这是由于group操作对每一个分组都返回一条记录,每组中包括一个Bag,所以exec方法中迭代处理Bag中记录就可以。
public Long exec(Tuple input) throws IOException {
try {
DataBag bag = (DataBag)input.get(0);
if(bag==null)
return null;
Iterator it = bag.iterator();
long cnt = 0;
while (it.hasNext()){
Tuple t = (Tuple)it.next();
if (t != null && t.size() > 0 && t.get(0) != null )
cnt++;
}
return cnt;
} catch (ExecException ee) {
throw ee;
} catch (Exception e) {
int errCode = 2106;
String msg = "Error while computing count in " + this.getClass().getSimpleName();
throw new ExecException(msg, errCode, PigException.BUG, e);
}
}
Algebraic 和Accumulator 接口
如前所述,具备algebraic性质的聚合函数在Map-Reduce过程中能被Combiner优化。直观来理解,具备algebraic性质的函数处理过程能被分为三部分:initial(初始化,处理部分输入数据)、intermediate(中间过程,处理初始化过程的结果)和final(收尾,处理中间过程的结果)。
比方COUNT函数,初始化过程为count计数操作。中间过程和收尾为sum求和操作。更进一步。假设函数在这三个阶段中都能进行同样的操作,那么函数具备distributive性质。比方SUM函数。
Pig提供了Algebraic 接口:
public interface Algebraic{
/**
* Get the initial function.
* @return A function name of f_init. f_init shouldbe an eval func.
* The return type off_init.exec() has to be Tuple
*/
public String getInitial(); /**
* Get the intermediatefunction.
* @return A function name of f_intermed. f_intermedshould be an eval func.
* The return type off_intermed.exec() has to be Tuple
*/
public String getIntermed(); /**
* Get the final function.
* @return A function name of f_final. f_final shouldbe an eval func parametrized by
* the same datum as the evalfunc implementing this interface.
*/
public String getFinal();
}
当中每一个方法都返回EvalFunc实现类的名称。
继续以COUNT函数为例,COUNT实现了Algebraic接口。针对下面语句:
input= load 'data' as (x, y);
grpd= group input by x;
cnt= foreach grpd generate group, COUNT(input);
storecnt into 'result';
Pig会重写MR运行计划:
Map
load,foreach(group,COUNT.Initial)
Combine
foreach(group,COUNT.Intermediate)
Reduce
foreach(group,COUNT.Final),store
Algebraic 接口通过Combiner优化降低传输数据量,而Accumulator接口则关注的是内存使用量。UDF实现Accumulator接口后,Pig保证全部key相同的数据(通过Shuffle)以增量的形式传递给UDF(默认pig.accumulative.batchsize=20000)。相同。COUNT也实现了Accumulator接口。
/* Accumulator interface implementation */
private long intermediateCount = 0L;
@Override
public void accumulate(Tuple b) throws IOException {
try {
DataBag bag = (DataBag)b.get(0);
Iterator it = bag.iterator();
while (it.hasNext()){
Tuple t = (Tuple)it.next();
if (t != null && t.size() > 0 && t.get(0) != null) {
intermediateCount += 1;
}
}
} catch (ExecException ee) {
throw ee;
} catch (Exception e) {
int errCode = 2106;
String msg = "Error while computing min in " + this.getClass().getSimpleName();
throw new ExecException(msg, errCode, PigException.BUG, e);
}
} @Override
public void cleanup() {
intermediateCount = 0L;
}
@Override
/*
*当前key都被处理完之后被调用
*/
public Long getValue() {
return intermediateCount;
}
前后端数据传递
通过UDFs构造函数传递数据是最简单的方法。然后通过define语句定义UDF实例时指定构造方法參数。但有些情况下。比方数据在执行期才产生,或者数据不能用String格式表达,这时候就得使用UDFContext了。
UDF通过getUDFContext方法获取保存在ThreadLoacl中的UDFContext实例。
UDFContext包括下面信息:
- jconf:Hadoop Configuration。
- clientSysProps:系统属性。
- HashMap<UDFContextKey,Properties> udfConfs:用户自己保存的属性,当中UDFContextKey由UDF类名生成。
UDFs运行流程
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaWRvbnR3YW50b2Jl/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
Pig架构可扩展性
Pig哲学之三——Pigs Live Anywhere。
理论上。Pig并不被限定执行在Hadoop框架上,有几个能够參考的实现和提议。
- Pigen。Pig on Tez。https://github.com/achalsoni81/pigeon,架构图例如以下:
- Pig的后端抽象层:https://wiki.apache.org/pig/PigAbstractionLayer。
眼下已经实现了PigLatin执行在Galago上。
參考资料
Pig官网:http://pig.apache.org/
Pig paper at SIGMOD 2008:Building a High Level DataflowSystem on top of MapReduce:The Pig Experience
Programming.Pig:Dataflow.Scripting.with.Hadoop(2011.9).Alan.Gates
Pig系统分析(8)-Pig可扩展性的更多相关文章
- Pig系统分析(7)-Pig有用工具类
Explain Explain是Pig提供的调试工具,使用explain能够输出Pig Lation的运行计划.值得一提的是,explain支持-dot选项.将运行计划以DOT格式输出, (DOT是一 ...
- Pig系统分析(5)-从Logical Plan到Physical Plan
Physical Plan生成过程 优化后的逻辑运行计划被LogToPhyTranslationVisitor处理,生成物理运行计划. 这是一个经典的Vistor设计模式应用场景. 当中,LogToP ...
- Pig系统分析(6)-从Physical Plan到MR Plan再到Hadoop Job
从Physical Plan到Map-Reduce Plan 注:由于我们重点关注的是Pig On Spark针对RDD的运行计划,所以Pig物理运行计划之后的后端參考意义不大,这些部分主要分析流程, ...
- pig 介绍与pig版 hello world
前两天使用pig做ETL,粗浅的看了一下,没有系统地学习,感觉pig还是值得学习的,故又重新看programming pig. 以下是看的第一章的笔记: What is pig? Pig provid ...
- pig简介
Apache Pig是MapReduce的一个抽象.它是一个工具/平台,用于分析较大的数据集,并将它们表示为数据流.Pig通常与 Hadoop 一起使用:我们可以使用Apache Pig在Hadoop ...
- Pig Latin程序设计1
Pig是一个大规模数据分析平台.Pig的基础结构层包括一个产生MapReduce程序的编译器.在编译器中,大规模并行执行依据存在.Pig的语言包括一个叫Pig Latin的文本语言,此语言有如下特性: ...
- Hive集成HBase;安装pig
Hive集成HBase 配置 将hive的lib/中的HBase.jar包用实际安装的Hbase的jar包替换掉 cd /opt/hive/lib/ ls hbase-0.94.2* rm -rf ...
- Hadoop Pig简介、安装、试用
相比Java的MapReduce api,Pig为大型数据集的处理提供了更高层次的抽象,与MapReduce相比,Pig提供了更丰富的数据结构,一般都是多值和嵌套的数据结构.Pig还提供了一套更强大的 ...
- Pig + Ansj 统计中文文本词频
最近特别喜欢用Pig,拥有能满足大部分需求的内置函数(built-in functions),支持自定义函数(user defined functions, UDF),能load 纯文本.avro等格 ...
随机推荐
- mysql left join,right join,inner join的区别
left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录 right join(右联接) 返回包括右表中的所有记录和左表中联结字段相等的记录 inner join(等值连接) ...
- mac 切换默认python版本
https://www.zhihu.com/question/30941329 首先终端的“python”命令会执行/usr/local/bin下的“python”链接,链接相当于win下的快捷方式, ...
- flask-compress的使用方法以及对应的http头Vary、Content-Encoding的意思
参考:https://github.com/shengulong/flask-compress 1.Content-Encoding是HTTP协议的响应报文头,一般形式如:Content-Encodi ...
- 《Javascript高级程序设计》的一些可疑点
1.null和undefined的区别(出自第三章基本概念的3.4数据类型) 2.sort-比较函数(5.2.5重排序方法)
- 手把手教你调试Entity Framework 6源码
0 摘要 本文讲述在Visual Studio 2013(VS 2013)下调试Entity Framework 6(EF 6)源码的配置过程.原则上,VS 2012也适用. 之前打算编写<E ...
- 全面了解linux服务器
一.查看linux服务器CPU详细情况 判断linux服务器CPU情况的依据如下 具有相同core id的CPU是同一个core的超线程 具有相同physical id的CPU是同一个CPU封装的线程 ...
- Laravel 5系列教程二:路由,视图,控制器工作流程
免费视频教程地址https://laravist.com/series/laravel-5-basic 上一篇教程我们走了那么长的路,终于把Laravel安装好了,这一篇教程我们就要进入Laravel ...
- 转:解决 java.util.MissingResourceException: Can't find bundle for base name com...config, locale zh_CN 错误
Solve java.util.MissingResourceException: Can't find bundle for base name com...config, locale zh_CN ...
- struts2入门示例(hello world)
1. 环境搭建 按照之前的文章配置好myeclipse的jdk和tomcat,并新建一个web项目后,可开始动手配置与struts2相关的地方了.首先去struts的官网下载好最新的struts2代码 ...
- LINUX经常使用命令小整理
系统操作: 1.重新启动机器:reboot. 2.查看某程序的进程:ps -ef|grep xxx(比如:ps -ef|grep tomcat). 3.查看当前linux系统系统版本号:lsb_rel ...