25、Hadoop与MongoDB集成:MapReduce作业实战

Hadoop与MongoDB集成:MapReduce作业实战

1. 执行首个示例MapReduce作业

在这个部分,我们将学习如何从源代码构建mongo - hadoop连接器,并设置Hadoop以独立模式运行示例。该连接器是使用Mongo中的数据在Hadoop上运行Hadoop MapReduce作业的核心。

准备工作
  • Hadoop发行版 :使用Apache Hadoop(http://hadoop.apache.org/),安装在Ubuntu Linux上。生产环境中,Apache Hadoop通常运行在Linux环境,Windows未经过生产系统测试,但开发时可以使用。Windows用户可安装VirtualBox(https://www.virtualbox.org/)等虚拟化环境,在其中设置Linux环境并安装Hadoop。
  • Git客户端 :用于将mongo - hadoop连接器的仓库克隆到本地文件系统,参考http://git - scm.com/book/en/Getting - Started - Installing - Git安装。
  • MongoDB :需安装在操作系统上,参考http://docs.mongodb.org/manual/installation/进行安装,并启动监听端口27017的mongod实例。
  • 知识储备 :不需要是Hadoop专家,但熟悉Hadoop和MapReduce概念会有帮助,可从http://en.wikipedia.org/wiki/MapReduce获取MapReduce编程的相关信息。
操作步骤
  1. 安装Java、Hadoop及所需包
    • 检查Java安装情况,在操作系统命令提示符输入:
$ javac –version
- 若程序未执行,提示需要包含javac的包,则安装Java:
$ sudo apt - get install default - jdk
  1. 下载Hadoop :从http://www.apache.org/dyn/closer.cgi/hadoop/common/下载版本2.4.0(或mongo - hadoop连接器支持的最新版本)。
  2. 解压Hadoop并配置
$ tar –xvzf <下载的.tar.gz文件名>
$ cd <解压目录>

打开 etc/hadoop/hadoop - env.sh 文件,将 export JAVA_HOME = ${JAVA_HOME} 替换为 export JAVA_HOME = /usr/lib/jvm/default - java
4. 克隆mongo - hadoop连接器代码

$ git clone https://github.com/mongodb/mongo - hadoop.git
$ cd mongo - hadoop 
  1. 创建软链接
$ ln –s <Hadoop安装目录> ~/hadoop - binaries

例如,若Hadoop解压到主目录:

$ ln –s ~/hadoop - 2.4.0 ~/hadoop - binaries

默认情况下,mongo - hadoop连接器会在 ~/hadoop - binaries 文件夹下查找Hadoop发行版。
6. 构建mongo - hadoop连接器

$./gradlew jar –Phadoop_version='2.4'

构建过程需要一些时间。
7. 导入数据到Mongo集合
假设mongod实例正在运行并监听端口27017,当前目录为mongo - hadoop连接器代码库的根目录,执行:

$ mongoimport - c yield_historical.in - d mongo_hadoop --drop examples/treasury_yield/src/main/resources/yield_historical_in.json
  1. 复制jar文件到lib目录
$ wget http://repo1.maven.org/maven2/org/mongodb/mongo - java - driver/2.12.0/mongo - java - driver - 2.12.0.jar
$ cp core/build/libs/mongo - hadoop - core - 1.2.1 - SNAPSHOT - hadoop_2.4.jar ~/hadoop - binaries/hadoop - 2.4.0/lib/
$ mv mongo - java - driver - 2.12.0.jar ~/hadoop - binaries/hadoop - 2.4.0/lib
  1. 执行MapReduce作业
~/hadoop - binaries/hadoop - 2.4.0/bin/hadoop jar examples/treasury_yield/build/libs/treasury_yield - 1.2.1 - SNAPSHOT - hadoop_2.4.jar \
com.mongodb.hadoop.examples.treasury.TreasuryYieldXMLConfig \
 - Dmongo.input.split_size = 8 - Dmongo.job.verbose = true \
 - Dmongo.input.uri = mongodb://localhost:27017/mongo_hadoop.yield_historical.in \
 - Dmongo.output.uri = mongodb://localhost:27017/mongo_hadoop.yield_historical.out

若输出中出现以下行,则表示MapReduce作业成功:

14/05/11 21:38:54 INFO mapreduce.Job: Job job_local1226390512_0001 completed successfully
  1. 查询输出集合
$ mongo
> use mongo_hadoop
switched to db mongo_hadoop
> db.yield_historical.out.find()
工作原理
  • 安装Hadoop并非易事,但为了运行mongo - hadoop连接器示例,我们只需下载存档、解压并以独立模式运行MapReduce作业。
  • 步骤1 - 6用于安装Hadoop,后续步骤克隆mongo - hadoop连接器代码并构建。
  • 导入数据到 yield_historical.in 集合作为MapReduce作业的输入。
  • 执行Hadoop命令时,指定的jar文件包含实现国库收益率示例MapReduce操作的类, com.mongodb.hadoop.examples.treasury.TreasuryYieldXMLConfig 类是入口点。
  • mongo.input.uri mongo.output.uri 分别指定MapReduce操作的输入和输出集合。
2. 关键类分析
TreasuryYieldXMLConfig

该类是MapReduce方法的入口点,包含 main 方法。使用mongo - hadoop连接器编写Mongo的MapReduce作业时,主类必须继承 com.mongodb.hadoop.util.MongoTool ,该类实现了 org.apache.hadoop.Tool 接口。

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.util.ToolRunner;
import com.mongodb.hadoop.MongoConfig;
import com.mongodb.hadoop.util.MongoTool;

public class TreasuryYieldXMLConfig extends MongoTool {
    static {
        // 加载配置文件
    }

    public static void main(String[] args) throws Exception {
        ToolRunner.run(new Configuration(), new TreasuryYieldXMLConfig(), args);
    }
}

有一个静态块从 hadoop - local.xml mongo - defaults.xml 两个XML文件加载配置。在构造函数中实例化 com.mongodb.hadoop.MongoConfig ,并设置输入输出格式、映射器和归约器类等重要配置。

映射器类 TreasuryYieldMapper
import org.apache.hadoop.io.DoubleWritable;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.mapreduce.Mapper;
import org.bson.BSONObject;

import java.io.IOException;
import java.util.Date;

public class TreasuryYieldMapper extends Mapper<Object, BSONObject, IntWritable, DoubleWritable> {
    @Override
    public void map(final Object pKey,
                    final BSONObject pValue,
                    final Context pContext)
            throws IOException, InterruptedException {
        final int year = ((Date) pValue.get("_id")).getYear() + 1900;
        double bid10Year = ((Number) pValue.get("bc10Year")).doubleValue();
        pContext.write(new IntWritable(year), new DoubleWritable(bid10Year));
    }
}

映射器继承 org.apache.hadoop.mapreduce.Mapper 类,读取输入文档的 _id 值(日期)提取年份,获取 bc10Year 字段的双精度值,将年份作为键,双精度值作为值写入上下文。

归约器类 TreasuryYieldReducer
import org.apache.hadoop.io.DoubleWritable;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.mapreduce.Reducer;
import org.bson.BasicBSONObject;
import org.bson.BSONWritable;

import java.io.IOException;
import java.util.Iterator;

public class TreasuryYieldReducer extends Reducer<IntWritable, DoubleWritable, IntWritable, BSONWritable> {
    @Override
    public void reduce(final IntWritable pKey, final Iterable<DoubleWritable> pValues, final Context pContext)
            throws IOException, InterruptedException {
        int count = 0;
        double sum = 0;
        Iterator<DoubleWritable> iterator = pValues.iterator();
        while (iterator.hasNext()) {
            DoubleWritable value = iterator.next();
            sum += value.get();
            count++;
        }
        final double avg = sum / count;
        BasicBSONObject output = new BasicBSONObject();
        output.put("count", count);
        output.put("avg", avg);
        output.put("sum", sum);
        pContext.write(pKey, new BSONWritable(output));
    }
}

归约器继承 org.apache.hadoop.mapreduce.Reducer 类,输入为映射器的输出。对相同键的双精度值进行求和、计数,计算平均值,并将结果写入上下文。

3. 编写首个Hadoop MapReduce作业

接下来,我们将使用Hadoop MapReduce API编写首个MapReduce作业,并使用mongo - hadoop连接器从MongoDB获取数据。

准备工作
  • 参考前面执行示例MapReduce作业的步骤设置mongo - hadoop连接器。
  • 该项目是Maven项目,需安装Maven,在Ubuntu Linux上执行:
$ sudo apt - get install maven
操作步骤
  1. 从Packt网站下载 Java mongo - hadoop - mapreduce - test 项目,该项目目标与之前使用MongoDB MapReduce框架的用例相同。
  2. 在项目根目录(包含 pom.xml 文件)的命令提示符下执行:
$ mvn clean package
  1. 生成的 mongo - hadoop - mapreduce - test - 1.0.jar 文件将保存在 target 目录。
  2. 假设CSV文件已导入 postalCodes 集合,在项目根目录执行以下命令:
~/hadoop - binaries/hadoop - 2.4.0/bin/hadoop \
jar target/mongo - hadoop - mapreduce - test - 1.0.jar \
com.packtpub.mongo.cookbook.TopStateMapReduceEntrypoint \
 - Dmongo.input.split_size = 8 \
 - Dmongo.job.verbose = true \
 - Dmongo.input.uri = mongodb://localhost:27017/test.postalCodes \
 - Dmongo.output.uri = mongodb://localhost:27017/test.postalCodesHadoopmrOut
  1. MapReduce作业完成后,打开mongo shell并执行查询:
$ mongo
> db.postalCodesHadoopmrOut.find().sort({count: - 1}).limit(5)
  1. 将输出与之前使用MongoDB MapReduce框架的结果进行比较。
工作原理
  • 项目包含三个类: TopStateMapReduceEntrypoint TopStateReducer TopStatesMapper
  • TopStatesMapper 类的 map 方法将州名作为键,整数值1作为值写入上下文:
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import org.bson.BSONObject;

import java.io.IOException;

public class TopStatesMapper extends Mapper<Object, BSONObject, Text, IntWritable> {
    @Override
    protected void map(Object key, BSONObject value, Context context) throws IOException, InterruptedException {
        context.write(new Text((String) value.get("state")), new IntWritable(1));
    }
}
  • TopStateReducer 类对相同州名的整数值求和:
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
import org.bson.BSONObject;
import org.bson.BasicBSONObject;
import org.bson.BSONWritable;

import java.io.IOException;
import java.util.Iterator;

public class TopStateReducer extends Reducer<Text, IntWritable, Text, BSONWritable> {
    @Override
    protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
        int sum = 0;
        Iterator<IntWritable> iterator = values.iterator();
        while (iterator.hasNext()) {
            IntWritable value = iterator.next();
            sum += value.get();
        }
        BSONObject object = new BasicBSONObject();
        object.put("count", sum);
        context.write(key, new BSONWritable(object));
    }
}
  • TopStateMapReduceEntrypoint 类的 main 方法设置配置并提交MapReduce作业:
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.util.ToolRunner;
import com.mongodb.hadoop.MongoConfig;
import com.mongodb.hadoop.MongoInputFormat;
import com.mongodb.hadoop.MongoOutputFormat;
import com.mongodb.hadoop.io.BSONWritable;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;

public class TopStateMapReduceEntrypoint {
    public static void main(String[] args) throws Exception {
        Configuration conf = new Configuration();
        MongoConfig config = new MongoConfig(conf);
        config.setInputFormat(MongoInputFormat.class);
        config.setMapperOutputKey(Text.class);
        config.setMapperOutputValue(IntWritable.class);
        config.setMapper(TopStatesMapper.class);
        config.setOutputFormat(MongoOutputFormat.class);
        config.setOutputKey(Text.class);
        config.setOutputValue(BSONWritable.class);
        config.setReducer(TopStateReducer.class);
        ToolRunner.run(conf, new TopStateMapReduceEntrypoint(), args);
    }
}

通过以上步骤,我们可以使用Hadoop和MongoDB进行数据处理和分析,实现MapReduce作业。后续还可以探索使用Hadoop Streaming用不同语言编写Map和Reduce函数。

Hadoop与MongoDB集成:MapReduce作业实战(续)

4. 代码结构与功能总结
类名 功能描述 关键代码片段
TreasuryYieldXMLConfig MapReduce作业的入口点,继承 MongoTool ,加载配置并启动作业 java<br>static {<br> // 加载配置文件<br>}<br>public static void main(String[] args) throws Exception {<br> ToolRunner.run(new Configuration(), new TreasuryYieldXMLConfig(), args);<br>}<br>
TreasuryYieldMapper 从输入文档提取年份和 bc10Year 值,写入上下文 java<br>final int year = ((Date) pValue.get("_id")).getYear() + 1900;<br>double bid10Year = ((Number) pValue.get("bc10Year")).doubleValue();<br>pContext.write(new IntWritable(year), new DoubleWritable(bid10Year));<br>
TreasuryYieldReducer 对相同年份的 bc10Year 值求和、计数、计算平均值,写入上下文 java<br>int count = 0;<br>double sum = 0;<br>Iterator<DoubleWritable> iterator = pValues.iterator();<br>while (iterator.hasNext()) {<br> DoubleWritable value = iterator.next();<br> sum += value.get();<br> count++;<br>}<br>final double avg = sum / count;<br>BasicBSONObject output = new BasicBSONObject();<br>output.put("count", count);<br>output.put("avg", avg);<br>output.put("sum", sum);<br>pContext.write(pKey, new BSONWritable(output));<br>
TopStateMapReduceEntrypoint 设置MapReduce作业的配置并提交作业 java<br>Configuration conf = new Configuration();<br>MongoConfig config = new MongoConfig(conf);<br>config.setInputFormat(MongoInputFormat.class);<br>config.setMapperOutputKey(Text.class);<br>config.setMapperOutputValue(IntWritable.class);<br>config.setMapper(TopStatesMapper.class);<br>config.setOutputFormat(MongoOutputFormat.class);<br>config.setOutputKey(Text.class);<br>config.setOutputValue(BSONWritable.class);<br>config.setReducer(TopStateReducer.class);<br>ToolRunner.run(conf, new TopStateMapReduceEntrypoint(), args);<br>
TopStatesMapper 将州名作为键,值为1写入上下文 java<br>context.write(new Text((String) value.get("state")), new IntWritable(1));<br>
TopStateReducer 对相同州名的值求和,写入上下文 java<br>int sum = 0;<br>Iterator<IntWritable> iterator = values.iterator();<br>while (iterator.hasNext()) {<br> IntWritable value = iterator.next();<br> sum += value.get();<br>}<br>BSONObject object = new BasicBSONObject();<br>object.put("count", sum);<br>context.write(key, new BSONWritable(object));<br>
5. 流程图分析
graph TD;
    A[开始] --> B[安装Java、Hadoop及所需包];
    B --> C[下载Hadoop];
    C --> D[解压Hadoop并配置];
    D --> E[克隆mongo - hadoop连接器代码];
    E --> F[创建软链接];
    F --> G[构建mongo - hadoop连接器];
    G --> H[导入数据到Mongo集合];
    H --> I[复制jar文件到lib目录];
    I --> J[执行MapReduce作业];
    J --> K{作业是否成功};
    K -- 是 --> L[查询输出集合];
    K -- 否 --> M[检查配置和代码];
    M --> J;
    N[编写MapReduce作业] --> O[准备工作];
    O --> P[下载项目];
    P --> Q[执行mvn命令打包];
    Q --> R[执行作业命令];
    R --> S{作业是否成功};
    S -- 是 --> T[查询结果并比较];
    S -- 否 --> U[检查配置和代码];
    U --> R;

该流程图展示了整个Hadoop与MongoDB集成实现MapReduce作业的流程,包括环境搭建、示例作业执行和自定义作业编写与执行等步骤。从开始安装Java、Hadoop等基础环境,到逐步构建mongo - hadoop连接器,导入数据,执行示例作业。之后是编写自定义MapReduce作业的流程,从准备工作到下载项目、打包、执行作业,最后根据作业是否成功进行相应处理。

6. 注意事项与常见问题
  • 环境配置 :在安装Java、Hadoop和MongoDB时,要确保版本兼容。例如,mongo - hadoop连接器支持的Apache Hadoop版本为2.4.0,在下载和配置时需注意。
  • 配置文件修改 :修改 etc/hadoop/hadoop - env.sh 文件时,要准确替换 JAVA_HOME 的值,否则可能导致Hadoop无法正常启动。
  • 数据导入 :使用 mongoimport 导入数据时,要确保文件路径和集合名称正确,并且mongod实例正在运行并监听正确的端口。
  • 代码编译和运行 :在使用Maven打包项目时,可能会遇到依赖下载失败的问题,可检查网络连接和Maven配置。执行作业时,若出现类找不到或配置错误,要仔细检查代码和配置文件。
7. 拓展应用
  • 使用不同语言编写MapReduce函数 :可以使用Hadoop Streaming,通过标准输出(stdout)在程序和Hadoop MapReduce框架之间进行通信,实现用Python等不同语言编写Map和Reduce函数。
  • 处理大规模数据 :可以结合Hadoop的分布式计算能力和MongoDB的存储能力,处理大规模数据。通过调整 mongo.input.split_size 等参数,优化数据处理性能。
  • 实时数据处理 :可以结合MongoDB的实时数据更新特性和Hadoop的流式处理框架,实现实时数据的处理和分析。

通过以上步骤和分析,我们可以深入理解Hadoop与MongoDB集成实现MapReduce作业的原理和方法,并且可以根据实际需求进行拓展和优化,实现更复杂的数据处理和分析任务。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值