Hadoop:Pipes接口实现

Hadoop入门教程:Pipes接口实现,Hadoop管道与流不同,流使用标准输入和输出让用户的Map和Reduce节点之间相互交流。而管道使用socket作为tasktracker与用户MapReduce进程之间的通道。下面我们同样使用Hadoop发行版中自带单词统计的例子,这个Map和Reduce函数是使用C/C++编写的,然后使用管道机制在Hadoop集群中运行用户的作业,在使用Hadoop Pipes时需要在头文件中包含hadoop/Pipes.hh、hadoop/TemplateFactory.hh、hadoop/StringUtils.hh这3个头文件。

需要注意的是Hadoop版本自带的Pipes例子中有三个实现,对应的源码文件分别为:wordcount-simple.cc、wordcount-part.cc及wordcount-nopipe.cc。下面对这三个文件进行说明。

wordcount-simple.cc,是最基本的Pipes编程,Mapper和Reducer使用C++编写,

RecordReader、Partitioner和RecordWriter均采用Hadoop内置的Java实现,其中,RecordReader为LineRecordReader(位于InputTextInputFormat中,按行读取数据,行所在的偏移量为key,行中的字符串为value),Partitioner为PipesPartitioner,RecordWriter为LineRecordWriter(位于InputTextOutputFormat中,输出格式为“key\tvalue\n”)。

wordcount-part.cc,Mapper、Partitioner和Reducer组件采用C++语言编写,其他组件采用Hadoop的java内置实现。

wordcount-nopipe.cc,RecordReader、Mapper、Reducer和RecordWriter均采用C++编写实现。

接下来介绍最简单的wordcount-simple.cc的Pipes的C++实现。

(1)Map实现

要实现WordCountMap就需要继承HadoopPipes::Mapper类,并实现Map函数,其代码如下:

class WordCountMap: public HadoopPipes: :Mapper {

public:

HadoopPipes: :TaskContext: :Counter* inputWords;

void map(HadoopPipes: :MapContext& context) {

std: :vector words =

HadoopUtils: :splitString(context.getInputValue(), " ");

for(unsigned int i=0; i < words.size(); ++i) {

context.emit(words[i], "1");

}

context.incrementCounter(inputWords, words.size());

}

};

从上述代码中很容易可以看出,Pipes接口是比较类似Java API接口的,通过MapContext类中的方法getInputValue( )获取value,就是每一行的值,处理之后通过MapContext类中的emit方法输出,这个输出也就是下一阶段Reduce的输入。

(2)Redcue实现

要实现WordCountReduce类,就需要继承HadoopPipes::Reducer类,并实现Reduce函数,代码如下:

class WordCountReduce: public HadoopPipes: :Reducer {

public:

HadoopPipes: :TaskContext: :Counter* outputWords;

void reduce(HadoopPipes: :ReduceContext& context) {

int sum = 0;

while (context.nextValue()) {

sum += HadoopUtils: :toInt(context.getInputValue());

}

context.emit(context.getInputKey(), HadoopUtils toString(sum));

context.incrementCounter(outputWords, 1);

}

};

从WordCountReduce类的实现中可以看出,Reduce通过ReduceContext类中的方法nextValue( )来获取当前key的下一个值value,然后对其值相加,最后通过emit方法提交键值对作为Redcue的最终输出。

(3)main函数

Map和Reduce实现之后,还需要一个main函数来驱动,需要调用HadoopPipes::runTask函数来驱动,代码如下:

int main(int argc, char *argv[]) {

return HadoopPipes: :runTask(HadoopPipes: :TemplateFactory

WordCountReduce>());

}

从main函数中可以看到,HadoopPipes::runTask函数有两个参数,分别就是Map和Reduce类。来源:CUUG官网

你可能感兴趣的:(hadoop)