因为工作的需要,意外的接触了阿里云ODPS.总得来说,和Hadoop生态体系还是有很多的相似之处的.工作中,很多的场景都可以写ODPS脚本去解决问题,但是毕竟类SQL的语言在一些场景下总是有些苍白,所以不得不学习MR去解决一些难题.工作的地方没有互联网,仅有一个PDF,周围没有人带..无奈的只好晚上加班补.我想吐槽自己一下自己的java…出道一年以来,从来没有用过debug.所有的程序只有两个场景,成功运行且答案正确,程序不能运行…..我想N年以后,自己一定会对自己的过往大笑不止的,
一个初级的MR程序Demo
1.目的:
假设有一个这样的场景,我需要统计一段期间中,某个网站的每天访问总量.
2.数据模拟:
输入表:demo_in
date string 日期
uid string UID
cnt bigint 访问次数
---------------
输出表:demo_out
date string 日期
cnt_cs bigint 访问总量
3.程序示例
package demo;
import com.aliyun.odps.OdpsException;
import com.aliyun.odps.data.Record;
import com.aliyun.odps.data.TableInfo;
import com.aliyun.odps.mapred.JobClient;
import com.aliyun.odps.mapred.MapperBase;
import com.aliyun.odps.mapred.ReducerBase;
import com.aliyun.odps.mapred.RunningJob;
import com.aliyun.odps.mapred.conf.JobConf;
import com.aliyun.odps.mapred.utils.InputUtils;
import com.aliyun.odps.mapred.utils.OutputUtils;
import com.aliyun.odps.mapred.utils.SchemaUtils;
import java.io.IOException;
import java.util.Iterator;
public class Demo {
/**
* 输入表:demo_in
* ---------------------------
* date string 日期
* uid sting uid
* cnt bigint 次数
* ---------------------------
*
* 输出表:demo_out
* ---------------------------
* date 日期
* CNT_CS 次数总和
*/
//Mapper
public static class DemoMapper extends MapperBase {
Record key;
Record value;
@Override
public void setup(TaskContext context) throws IOException {
key=context.createMapOutputKeyRecord();
value=context.createMapOutputValueRecord();
}
@Override
public void map(long recordNum, Record record, TaskContext context) throws IOException {
//TODO
key.setString("date",record.getString("date"));
value.setBigint("cnt",record.getBigint("cnt"));
context.write(key,value);
}
@Override
public void cleanup(TaskContext context) throws IOException {
}
}
//Reducer
public static class DemoReducer extends ReducerBase {
Record result;
@Override
public void setup(TaskContext context) throws IOException {
result=context.createOutputRecord();
}
@Override
public void reduce(Record key, Iterator<Record> values, TaskContext context) throws IOException {
long cnt_cs=0L;
while (values.hasNext()) {
Record val = values.next();
cnt_cs+=val.getBigint("cnt");
}
result.setString("date",key.getString("date"));
result.setBigint("cnt_cs",cnt_cs);
context.write(result);
}
@Override
public void cleanup(TaskContext context) throws IOException {
}
}
public static void main(String[] args) throws OdpsException {
if (args.length!=2){
System.err.println("Need To args..");
System.exit(2);
}
JobConf job = new JobConf();
// TODO: specify map output types
job.setMapOutputKeySchema(SchemaUtils.fromString("date:string"));
job.setMapOutputValueSchema(SchemaUtils.fromString("cnt:bigint"));
// TODO: specify input and output tables
InputUtils.addTable(TableInfo.builder().tableName(args[0]).build(), job);
OutputUtils.addTable(TableInfo.builder().tableName(args[1]).build(), job);
// TODO: specify a mapper
job.setMapperClass(demo.DemoMapper.class);
// TODO: specify a reducer
job.setReducerClass(demo.DemoReducer.class);
RunningJob rj = JobClient.runJob(job);
rj.waitForCompletion();
}
}
4.运行:在写的时候,用的是IDEA,阿里云有这个的一个插件,很好用.运行这个案例的时候,需要编辑运行参数:
5.总结:官方给的案例并不多,网上的资料也给没有多少.真心对一个java初学者来说,太难了.很好奇写这些代码的人是怎么想出来的.不皮了…其实,这个并不是很难,在了解这个基本框架后,就能迅速上手了.关键是处理问题的思路,而不是一直纠结于如何实现的具体细节上.不要被困难吓到.加油,少年