阿里云ODPS-MR学习

因为工作的需要,意外的接触了阿里云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初学者来说,太难了.很好奇写这些代码的人是怎么想出来的.不皮了…其实,这个并不是很难,在了解这个基本框架后,就能迅速上手了.关键是处理问题的思路,而不是一直纠结于如何实现的具体细节上.不要被困难吓到.加油,少年

Guess you like

Origin blog.csdn.net/qq_30901367/article/details/81952337