百度在使用Hadoop过程中同样发现了Hadoop因为Java语言带来的低效问题,并对Hadoop进行扩展。



而在此之前,百度也尝试了 Hadoop PIPES 和 Hadoop Streamming,但是发现这些问题:

- 这两种方案都无法很好地控制Child JVM(Map TaskTracker和Reduce TaskTracker)内存的使用,这部分都由JVM自己控制,而你能做的就只是使用-Xmx设置内存限制而已;

- 这两种方案都只能影响到Mapper和Reducer回调函数,而真正影响性能的sort和shuffle过程依然在Java实现的TaskTracker中执行完成;

- 数据流问题。两种方案中,数据处理流都必须由TaskTracker流向Mapper或者Reducer然后再流回来。而无论是使用pipeline还是socket方式传递数据,都难以避免数据的移动。对于大规模数据处理,其代价是不可忽视的。



究其根本,实际上是C++模块所承担的逻辑太少。于是百度提出了更彻底的方案,即"Hadoop C++ Extention",该方案中C++代码对Hadoop入侵得更多。它将原来TaskTracker中完成的数据处理工作都交给C++模块去完成,而只让其负责协议通信和控制等。如此一来,上面的问题就都解决了:

- TaskTracker JVM只负责少量通信工作,其内存需求很小并且可以预见,从而容易控制,譬如设为-Xmx100m就足够了;

- sort和shuffle过程都使用C++模块实现,性能得到提高;

- 数据在其整个生命周期都只在C++模块中,避免不必要的移动。

这就犹如将C++模块的战线往前推进了。当然,也许在很多人看来,这只是五十步与百步的区别,但是这多出来的五十步,

两种的方式的具体例子:

一,Pipes方式:

首先,建立相应的目录:

> hadoop fs –mkdir name

> hadoop fs –mkdir name/input

>hadoop fs –put file1.txt file2.txt name/input

1、编写程序(wordcount.cpp)

#include<algorithm>

#include<limits>

#include<string>

#include"stdint.h"

#include"hadoop/Pipes.hh"

#include"hadoop/TemplateFactory.hh"

#include"hadoop/StringUtils.hh"

usingnamespace std;

class WordCountMapper:publicHadoopPipes::Mapper

{

public:

WordCountMapper(HadoopPipes::TaskContext&context){}

void map(HadoopPipes::MapContext& context)

{

string line =context.getInputValue();

vector<string>word = HadoopUtils::splitString(line," ");

for (unsignedint i=0; i<word.size(); i++)

{

context.emit(word[i],HadoopUtils::toString(1));

}

}

};

class WordCountReducer:publicHadoopPipes::Reducer

{

public:

WordCountReducer(HadoopPipes::TaskContext&context){}

void reduce(HadoopPipes::ReduceContext& context)

{

int count = 0;

while (context.nextValue())

{

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

}

context.emit(context.getInputKey(),HadoopUtils::toString(count));

}

};

int main(int argc,char **argv)

{

returnHadoopPipes::runTask(HadoopPipes::TemplateFactory<WordCountMapper,WordCountReducer>());

}

2、编写makefile

CC = g++

HADOOP_INSTALL =../../data/users/hadoop/hadoop/

PLATFORM = Linux-amd64-64

CPPFLAGS = -m64-I$(HADOOP_INSTALL)/c++/$(PLATFORM)/include

wordcount:wordcount.cpp

$(CC) $(CPPFLAGS) $< -Wall -L$(HADOOP_INSTALL)/c++/$(PLATFORM)/lib-lhadooppipes -lhadooputils -lpthread -g -O2 -o $@

3、编译程序并且放入hadoop系统

> make wordcount

> hadoop fs –put wordcount name/worcount

4、编写配置文件(job_config.xml)

<?xml version="1.0"?>

<configuration>

<property>

<name>mapred.job.name</name>

<value>WordCount</value>

</property>

<property>

<name>mapred.reduce.tasks</name>

<value>10</value>

</property>

<property>

<name>mapred.task.timeout</name>

<value>180000</value>

</property>

<property>

<name>hadoop.pipes.executable</name>

<value>/user/hadoop/name/wordcount</value>

<description> Executable path is given as"path#executable-name"

sothat the executable will havea symlink in working directory.

This can be used for gdbdebugging etc.

</description>

</property>

<property>

<name>mapred.create.symlink</name>

<value>yes</value>

</property>

<property>

<name>hadoop.pipes.java.recordreader</name>

<value>true</value>

</property>

<property>

<name>hadoop.pipes.java.recordwriter</name>

<value>true</value>

</property>

</configuration>

<property>

<name>mapred.child.env</name>

<value>LD_LIBRARY_PATH=/data/lib</value> <!--如果用到动态库: lib库的路径,要保证每台机器上都有 -->

<description>User added environment variables for the task tracker child

processes. Example :

1) A=foo This will set the env variable A to foo

2) B=$B:c This is inherit tasktracker's B env variable.

</description>

</property>

<property>

<name>mapred.cache.files</name>

<value>/user/hadoop/name/data#data</value> <!--如果用到外部文件:hadoop上的data路径,程序中fopen("data/file.txt", "r") -->

</property>

5、运行程序

> hadoop pipes -conf ./job_config.xml -input/user/hadoop/name/input/* -output /user/hadoop/name/output -program/user/hadoop/name/wordcount

(注:output文件夹在运行前不能建立,系统会自己建立)

这个例子很简单,只是统计词频,但是,实际的数据挖掘比较复杂,尤其涉及到中文,很多情况下要进行分词,那就要初始化一些分词句柄及空间,然后分词处理,其实可以将MapReduce程序看成普通的C++程序,要初始化东西,放到构造函数,具体处理放到Map和Reduce里。

二,Streaming方式:

1、 首先编写map程序(map.cpp)

#include <string>

#include <iostream>

using namespace std;

int main()

{

string line;

while(cin>>line)//如果是中文的话,用fgets(char*, int n, stdin)读进来,再分词处理

{

cout<<line<<"\t"<<1<<endl;

}

return 0;

}

>>g++ -o map map.cpp

2、 编写reduce程序(reduce.cpp)

#include <map>

#include <string>

#include <iostream>

using namespace std;

int main()

{

string key;

string value;

map<string,int> word_count;

map<string,int> :: iterator it;

while(cin>>key)

{

cin>>value;

it= word_count.find(key);

if(it!= word_count.end())

{

++(it->second);

}

else

{

word_count.insert(make_pair(key,1));

}

}

for(it= word_count.begin(); it != word_count.end(); ++it)

cout<<it->first<<"\t"<<it->second<<endl;

return 0;

}

>>g++ -o reduce reduce.cpp

3、 需要统计的文件,并提交至hadoop中

File1.txt:hello hadoop helloworld

File2.txt:this is a firsthadoop

>>hadoop fs –put File1.txt File2.txt ans

4、 运行程序

>>hadoop jar /data/users/hadoop/hadoop/contrib/streaming/hadoop-streaming-0.20.9.jar-file
map -file reduce -input ans/* -output output1 -mapper /data/name/hadoop_streaming/map -reducer /data/name/hadoop_streaming/reduce

hadoop上C++开发两种方式的例子的更多相关文章

  1. curl文件上传有两种方式,一种是post_fileds,一种是infile

    curl文件上传有两种方式,一种是POSTFIELDS,一种是INFILE,POSTFIELDS传递@实际地址,INFILE传递文件流句柄! );curl_setopt($ch, CURLOPT_PO ...

  2. 将HTML页面自动保存为PDF文件并上传的两种方式(一)-前端(react)方式

    一.业务场景 公司的样本检测报告以React页面的形式生成,已调整为A4大小的样式并已实现分页,业务上需要将这个网页生成PDF文件,并上传到服务器,后续会将这个文件发送给客户(这里不考虑). 二.原来 ...

  3. 利用Selenium实现图片文件上传的两种方式介绍

    在实现UI自动化测试过程中,有一类需求是实现图片上传,这种需求根据开发的实现方式,UI的实现方式也会不同. 一.直接利用Selenium实现 这种方式是最简单的一种实现方式,但是依赖于开发的实现. 当 ...

  4. hadoop 读取文件的两种方式

    1.操作javaAPI方式 static{ URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory()); } public stat ...

  5. ASP.NET Core 1.0中实现文件上传的两种方式(提交表单和采用AJAX)

    Bipin Joshi (http://www.binaryintellect.net/articles/f1cee257-378a-42c1-9f2f-075a3aed1d98.aspx) Uplo ...

  6. FORM开发两种方式实现动态LIST

    方法一:常规的,也是网上比较常见的 1.将目标ITEM的子类信息设置为List,不需要添加列表中元素,不需要初始值. 2.新建一个Procedure,代码如下: PROCEDURE basis_lis ...

  7. Java文件上传的几种方式

    文件上传与文件上传一样重要.在Java中,要实现文件上传,可以有两种方式: 1.通过Servlet类上传 2.通过Struts框架实现上传 这两种方式的根本还是通过Servlet进行IO流的操作. 一 ...

  8. Hadoop之HDFS文件操作常有两种方式(转载)

    摘要:Hadoop之HDFS文件操作常有两种方式,命令行方式和JavaAPI方式.本文介绍如何利用这两种方式对HDFS文件进行操作. 关键词:HDFS文件    命令行     Java API HD ...

  9. MyBatis开发Dao层的两种方式(Mapper动态代理方式)

    MyBatis开发原始Dao层请阅读我的上一篇博客:MyBatis开发Dao层的两种方式(原始Dao层开发) 接上一篇博客继续介绍MyBatis开发Dao层的第二种方式:Mapper动态代理方式 Ma ...

随机推荐

  1. RunLoop总结:RunLoop基础知识

    没有实际应用场景,很难理解一些抽象空洞的东西,所以前面几篇文章先介绍了RunLoop的几个使用场景. 另外AsyncDisplayKit中也有大量使用RunLoop的示例. 关于实际的使用RunLoo ...

  2. 用Netty解析Redis网络协议

    用Netty解析Redis网络协议 根据Redis官方文档的介绍,学习了一下Redis网络通信协议.然后偶然在GitHub上发现了个用Netty实现的Redis服务器,很有趣,于是就动手实现了一下! ...

  3. Cassandra User 问题汇总(1)------------repair

    Cassandra Repair 问题 问1: 文档建议每周或者每月跑一次full repair.那么如果我是使用partition rangerepair,是否还有必要在cluster的每个节点上定 ...

  4. 如何将一个二进制的xxx.bin文件轻松转为C语言数组

    今天在写一个SPI-flash读写程序,目的是要将一个二进制文件写到SPI_FLASH中,最后通过开机读取,实际上这个.bin文件就是uboot和second-boot的结合体.通过SD卡写到SPI- ...

  5. EBS销售订单挑库发放处理程序

    来自:http://blog.csdn.net/cunxiyuan108/article/details/6014769 在EBS实施中,经常遇到从外部传进来一个被登记的销售订单,需要通过程序进行销售 ...

  6. Eclipse开发C/C++ 安装配置

    1.       jdk环境配置 2.       eclipse 下载 3.       MinGW 下载安装 4.       编写Hello Word jdk环境配置 环境配置我就不多说了,网上 ...

  7. struts1.x mvc简单例程

    因为项目需要,需要使用struts1.x .因此学习下struts框架. 例程从struts 实现MVC框架入手,完成一次request请求. 一.前台 两个jsp文件 index.jsp: 只有一个 ...

  8. linux下连接windows的远程桌面

    拿ubuntu来举例: 1安装rdesktop 2 rdesktop -f 196.168.1.11:3389 3 哦鸟

  9. Android开发学习之路--Activity之生命周期

    其实这篇文章应该要在介绍Activity的时候写的,不过那个时候还不怎么熟悉Activity,还是在这里详细介绍下好了.还是参考下官方文档的图吧: 从上面的流程,我们可以看出首先就是打开APP,开始执 ...

  10. Android初级教程使用服务注册广播接收者监听手机解锁屏变化

    之前第七章广播与服务理论篇写到: 特殊的广播接收者(一般发广播次数频率很高) 安卓中有一些广播接收者,必须使用代码注册,清单文件注册是无效的 屏幕锁屏和解锁 电量改变 今天在这里就回顾一下,且用代码方 ...