MapReduce编写的正确姿势
- 先看一下目录结构
这里是job接口,负责参数的传递和定时的调用
下面的图是MR 程序相关的目录图片,其中MR的入口程序负责读取数据,并指定对应的Map、Reduce程序。
- 程序的流程
首先简单的说一下,整体的流程:
- 首先是一个Job(定时任务),定时调用 入口程序,拼装参数。
- job调用 MR的入口程序,入口程序获得job传入的参数,根据参数获得所需的数据;可以去Hbase、mysql、HDFS中获取数据;这个文件会配置job名、要调用的Mapper、Reduce,添加需要的jar包
- 数据传入Mapper程序,Mapper程序进行数据的整合,整合完成的数据会变成:key:{value1,value2,value3,...}这个样子,所以传入Reduce的value应该是一个可迭代的参数(在这里坑了一会)。Mapper将所有的数据整合完成后,会进入Reduce程序
- Reduce程序,接受参数,参数类型要和Mapper的返回类型是一样的;values 的入参是 一个可迭代的类型,泛型必须与Mapper的value返回类型一致。然后根据需求进行处理。
- 上代码
Job程序:
- package com.sky.cy.mapreduce.dispatch;
- import com.sky.cy.mapreduce.util.BasicMapreduceJob;
- import com.ssports.util.LogFormat;
- import com.ssports.util.ToolUtil;
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- import org.springframework.stereotype.Component;
- import java.util.Date;
- /**
- * @描述:
- * @文件名: UserActionRecordStatistJob
- * @创建人: YangLianjun
- * @创建时间: 2019/4/2 9:58
- * @修改人:
- * @修改备注: Copyright 北京和信金谷科技有限公司 2019/4/2
- */
- @Component
- public class UserActionRecordStatistJob extends BasicMapreduceJob {
- public static Log log = LogFactory.getLog(UserActionRecordStatistJob.class);
- @Override
- public String[] preProcessJob(String... args) {
- log.info(LogFormat.formatMsg("UserActionRecordStatistJob.preProcessJob","","UserActionRecordStatistJob is start"));
- String statTimeStr = "";
- if (args != null && args.length == 1) {
- statTimeStr = args[0];
- } else {
- Date date = ToolUtil.addDay(new Date(), -1);
- String statTime = ToolUtil.getDateStr(date, "yyyyMMdd");
- // String statTime = "20190401";
- log.info(LogFormat.formatMsg("UserActionRecordStatistJob.preProcessJob","statTime:"+statTime,""));
- statTimeStr = statTime;
- }
- String[] retArgs = new String[2];
- // 这个参数是指定哪个 MR入口程序
- retArgs[0] = "com.sky.cy.mapreduce.job.UserActionRecordStatistMR" ;
- retArgs[1] = statTimeStr;
- return retArgs;
- }
- }
MR入口程序,负责数据的读取,指定对应的Map、Reduce程序:
- package com.sky.cy.mapreduce.job;
- import com.sky.cy.mapreduce.job.mapper.UserActionRecordMapper;
- import com.sky.cy.mapreduce.job.mapper.UserActionRecordStatistMapper;
- import com.sky.cy.mapreduce.job.reducer.UserActionRecordReducer;
- import com.sky.cy.mapreduce.job.reducer.UserActionRecordStatistReducer;
- import com.sky.cy.mapreduce.util.BasicMapreduce;
- import com.ssports.util.LogFormat;
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- import org.apache.hadoop.conf.Configuration;
- import org.apache.hadoop.fs.Path;
- import org.apache.hadoop.hbase.client.Scan;
- import org.apache.hadoop.hbase.filter.*;
- import org.apache.hadoop.hbase.mapreduce.MultiTableOutputFormat;
- import org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil;
- import org.apache.hadoop.hbase.util.Bytes;
- import org.apache.hadoop.io.Text;
- import org.apache.hadoop.mapreduce.Job;
- import java.io.IOException;
- /**
- * @描述:
- * @文件名: UserActionRecordStatistMR
- * @创建人: YangLianjun
- * @创建时间: 2019/4/2 14:47
- * @修改人:
- * @修改备注: Copyright 北京和信金谷科技有限公司 2019/4/2
- */
- public class UserActionRecordStatistMR extends BasicMapreduce {
- public static final Log LOG = LogFactory.getLog(UserActionRecordStatistMR.class);
- public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
- LOG.info(LogFormat.formatMsg("UserActionRecordStatistMR.main","","start ..."));
- init();
- String statTime = args[0];
- // 将日期作为查询条件
- Filter filter = new SingleColumnValueFilter(Bytes.toBytes("f"),Bytes.toBytes("stat_time"), CompareFilter.CompareOp.EQUAL,Bytes.toBytes(statTime)) ;
- Scan scan = new Scan();
- scan.setFilter(filter);
- Configuration configuration = defaultHbaseConfiguration();
- configuration.set("statTime",statTime);
- Job job = Job.getInstance(configuration, "UserActionRecordStatistMR");
- TableMapReduceUtil.initTableMapperJob(UserActionRecordStatistMR.Constants.HBASE_FILTER_TABLE, scan, UserActionRecordStatistMapper.class, Text.class, Text.class, job);
- job.setReducerClass(UserActionRecordStatistReducer.class);
- job.setNumReduceTasks(1);
- job.setOutputFormatClass(MultiTableOutputFormat.class);
- //添加mysql驱动包
- job.addFileToClassPath(new Path(UserActionMR.Constants.MYSQL_JAR_PATH));
- //添加spring的jar
- job.addFileToClassPath(new Path(ActionFilterStatistMR.Constants.SPRING_CONTEXT_JAR_PATH));
- job.addFileToClassPath(new Path(ActionFilterStatistMR.Constants.SPRING_TX_JAR_PATH));
- job.addFileToClassPath(new Path(ActionFilterStatistMR.Constants.SPRING_AOP_JAR_PATH));
- job.addFileToClassPath(new Path(ActionFilterStatistMR.Constants.SPRING_BEAN_HADOOP_PATH));
- job.addFileToClassPath(new Path(ActionFilterStatistMR.Constants.SPRING_DATA_HADOOP_PATH));
- job.waitForCompletion(true);
- }
- public static class Constants {
- //需要获取的hbase数据的表名
- public static final String HBASE_FILTER_TABLE = "sky_user_action_record";
- }
- }
Map程序:
- package com.sky.cy.mapreduce.job.mapper;
- import com.sky.cy.mapreduce.util.HbaseUtil;
- import com.sky.cy.mapreduce.util.RegexUtil;
- import com.ssports.util.LogFormat;
- import com.ssports.util.SpringHelper;
- import com.ssports.util.ToolUtil;
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- import org.apache.hadoop.hbase.client.Result;
- import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
- import org.apache.hadoop.hbase.mapreduce.TableMapper;
- import org.apache.hadoop.io.Text;
- import java.io.IOException;
- /**
- * @描述:
- * @文件名: UserActionRecordStatistMapper
- * @创建人: YangLianjun
- * @创建时间: 2019/4/2 14:46
- * @修改人:
- * @修改备注: Copyright 北京和信金谷科技有限公司 2019/4/2
- */
- public class UserActionRecordStatistMapper extends TableMapper<Text, Text> {
- private static final Log log = LogFactory.getLog(UserActionRecordStatistMapper.class);
- public static final String FAMILY_F = "f";
- protected void map(ImmutableBytesWritable key, Result result, Context context) throws IOException, InterruptedException {
- log.info(LogFormat.formatMsg("UserActionRecordStatistMapper.map", "", "mapper start ..."));
- String userId = HbaseUtil.getValue(FAMILY_F, "user_id", result);
- String actionName = HbaseUtil.getValue(FAMILY_F,"action_name",result) ;
- String actionId = HbaseUtil.getValue(FAMILY_F,"action_id",result) ;
- String statTime = context.getConfiguration().get("statTime");
- String keyOut = userId + ":" + statTime;
- log.info(LogFormat.formatMsg("UserActionRecordStatistMapper.map", "keyOut:"+keyOut, ""));
- Text text = new Text(keyOut);
- String valueOut = actionId + ":"+actionName;
- log.info(LogFormat.formatMsg("UserActionRecordStatistMapper.map", "valueOut:"+valueOut, ""));
- Text value = new Text(valueOut);
- context.write(text, value);
- log.info(LogFormat.formatMsg("UserActionRecordStatistMapper.map", "", "mapper end ..."));
- }
- }
Reduce程序:
- package com.sky.cy.mapreduce.job.reducer;
- import com.sky.cy.log.base.dao.SkyUserActionRecordStatistMapper;
- import com.ssports.util.LogFormat;
- import com.ssports.util.SpringHelper;
- import com.ssports.util.ToolUtil;
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- import org.apache.hadoop.hbase.mapreduce.TableReducer;
- import org.apache.hadoop.io.NullWritable;
- import org.apache.hadoop.io.Text;
- import java.io.IOException;
- import java.util.*;
- /**
- * @描述:
- * @文件名: UserActionRecordStatistReducer
- * @创建人: YangLianjun
- * @创建时间: 2019/4/2 14:47
- * @修改人:
- * @修改备注: Copyright 北京和信金谷科技有限公司 2019/4/2
- */
- public class UserActionRecordStatistReducer extends TableReducer<Text, Text, NullWritable> {
- private static final Log log = LogFactory.getLog(UserActionRecordStatistReducer.class);
- private static final Integer ALL = 1 ; // 统计状态,全部统计
- protected void setup(Context context) throws IOException, InterruptedException {
- SpringHelper.init("classpath*:spring/*.xml");
- }
- protected void reduce(Text key, Iterable<Text> values, Context context){
- log.info(LogFormat.formatMsg("UserActionRecordStatistReducer.reduce","","start ..."));
- String keyRow = new String(key.getBytes());
- String[] keys = keyRow.split(":");
- String userId = keys[0] ;
- log.info(LogFormat.formatMsg("UserActionRecordStatistReducer.reduce","userId:"+userId,""));
- String statTime = keys[1] ;
- log.info(LogFormat.formatMsg("UserActionRecordStatistReducer.reduce", "key:"+keyRow, ""));
- List<String> actionList = new ArrayList<>();
- for (Text value : values) {
- log.info(LogFormat.formatMsg("UserActionRecordStatistReducer.reduce", "value:"+value.toString(), ""));
- actionList.add(value.toString()) ;
- }
- SkyUserActionRecordStatistMapper mapper = SpringHelper.getBean("skyUserActionRecordStatistMapper") ;
- com.sky.cy.log.base.bean.SkyUserActionRecordStatistEntity entity = new com.sky.cy.log.base.bean.SkyUserActionRecordStatistEntity() ;
- Set<String> uniqueSet = new HashSet<>(actionList) ;
- for (String s : uniqueSet) {
- String actionId = s.split(":")[0] ;
- log.info(LogFormat.formatMsg("UserActionRecordStatistReducer.reduce","actionId:"+actionId,""));
- String actionName = s.split(":")[1] ;
- int actionNumber = Collections.frequency(actionList, s) ; //统计出来数量
- entity = mapper.selectTotalByIdAndType(userId,actionId,ALL) ; //查询全部统计 的信息
- if (null == entity){ //不存在 这个信息,插入
- log.info(LogFormat.formatMsg("UserActionRecordStatistReducer.reduce","","insert start ..."));
- com.sky.cy.log.base.bean.SkyUserActionRecordStatistEntity entity1 = new com.sky.cy.log.base.bean.SkyUserActionRecordStatistEntity() ;
- entity1.setUserId(userId);
- entity1.setActionId(actionId);
- entity1.setActionName(actionName);
- entity1.setStatistTotal(actionNumber);
- entity1.setStatistTime(statTime);
- entity1.setStatistType(ALL);
- int insert = mapper.insertSelective(entity1) ;
- log.info(LogFormat.formatMsg("UserActionRecordStatistReducer.reduce","insert number:"+insert,""));
- }else { //存在,进行更新
- log.info(LogFormat.formatMsg("UserActionRecordStatistReducer.reduce","","update start..."));
- int update = mapper.updateTotalAndDays(userId,actionId,actionNumber,ALL) ; //更新
- log.info(LogFormat.formatMsg("UserActionRecordStatistReducer.reduce","update number:"+update,"update end..."));
- }
- }
- }
- }
说明:
利用集群进行整合、计算、归纳,本身是一个特别复杂的事情,Hadoop中的MR框架可以让我们从复杂的操作中解脱出来,只关注于逻辑本身,无疑是程序员的福音。只要理解了MR的流程和基本的运作原理,就可以像写java程序那样简单的对数据进行处理,但是却比单机的java程序效率高得多。当然既然使用到了MR,数据量应该是巨大的,如果只是对单机mysql中的数据进行统计与计算,建议还是使用普通的方式,毕竟最适合自己才是最好的!!!
MapReduce编写的正确姿势的更多相关文章
- (转)Git 提交的正确姿势:Commit message 编写指南
Git 每次提交代码,都要写 Commit message(提交说明),否则就不允许提交. $ git commit -m "hello world" 上面代码的-m参数,就是用来 ...
- 开发函数计算的正确姿势 —— 使用 Fun Local 本地运行与调试
前言 首先介绍下在本文出现的几个比较重要的概念: 函数计算(Function Compute): 函数计算是一个事件驱动的服务,通过函数计算,用户无需管理服务器等运行情况,只需编写代码并上传.函数计算 ...
- Git 提交的正确姿势
Git 提交的正确姿势:Commit message 编写指南 SCOP范围 middleware core config plugin test type范围 Git 每次提交代码,都要写 Comm ...
- IphoneX适配正确姿势
IphoneX适配正确姿势 写在前面 距离18年9月iphonex发布以来已经快两年了(所以对于iphonex机型的头部刘海(sensor housing)和底部小黑条(Home Indicator) ...
- 判断是否为gif/png图片的正确姿势
判断是否为gif/png图片的正确姿势 1.在能取到图片后缀的前提下 1 2 3 4 5 6 7 8 9 //假设这是一个网络获取的URL NSString *path = @"http:/ ...
- 在Linux(ubuntu server)上面安装NodeJS的正确姿势
上一篇文章,我介绍了 在Windows中安装NodeJS的正确姿势,这一篇,我们继续来看一下在Linux上面安装和配置NodeJS. 为了保持一致,这里也列举三个方法 第一个方法:通过官网下载安装 h ...
- 程序员取悦女朋友的正确姿势---Tips(iOS美容篇)
前言 女孩子都喜欢用美图工具进行图片美容,近来无事时,特意为某人写了个自定义图片滤镜生成器,安装到手机即可完成自定义滤镜渲染照片.app独一无二,虽简亦繁. JH定律:魔镜:最漂亮的女人是你老婆魔镜: ...
- ios监听ScrollView/TableView滚动的正确姿势
主要介绍 监测tableView垂直滚动的舒畅姿势 监测scrollView/collectionView横向滚动的正确姿势 1.监测tableView垂直滚动的舒畅姿势 通常我们用KVO或者在scr ...
- 玩转 Ceph 的正确姿势
玩转 Ceph 的正确姿势 本文先介绍 Ceph, 然后会聊到一些正确使用 Ceph 的姿势:在集群规模小的时候,Ceph 怎么玩都没问题:但集群大了(到PB级别),这些准则可是保证集群健康运行的不二 ...
随机推荐
- c++多线程编程(三)
关于WaitForSingleObject函数用法 : 用户模式的线程同步机制效率高,如果需要考虑线程同步问题,应该首先考虑用户模式的线程同步方法. 但是,用户模式的线程同步有限制,对于多个进程之间的 ...
- FZU2282 Wand
题意 n个数字,要求至少k个数字位置不变,其余进行错排的方案数 分析 错排公式: D(n)=(n-1)[D(n-2)+D(n-1)] 如果n个数字,i个数字位置不变,其余进行错排的的方案数是C(n, ...
- codeforce453DIV2——D. GCD of Polynomials
题意 给出n(1–150). 输出两个多项式A,B从常数到最高次的系数,使得对两个多项式求gcd时,恰好经过n步得到结果. 多项式的gcd一步是指(A(x),B(x))变成(B,A mod B)的过程 ...
- codeforce469DIV2——C. Zebras
题意 0, 010, 01010 这一类的01交替且开头和结尾都为0的序列被称为zebra序列.给出一段01序列,尝试能否把他分为k个子序列使得每个子序列都是zebra序列. 分析 这个题应该算是水题 ...
- 8.INSERT INTO 语句 UPDATE 语句
1. INSERT INTO 语句 INSERT INTO 语句用于向表格中插入新的行. 语法 INSERT INTO 表名称 VALUES (值1, 值2,....) INSERT INTO Per ...
- Yii2视频
Yii2 视频分享 需要的小伙伴看过来链接: https://pan.baidu.com/s/1sl4H0RV 密码: nknx (有问题请留言)
- HttpUploader7-授权码配置
1.1. 七牛云存储 配置方式: 1.配置授权码 2.配置云存储 3.配置空间名称 4.配置上传地址 1.2. 阿里云存储 配置方式: 1.填写授权码 2.配置云存储为阿里云 ...
- 策略与计费控制规则(Policy and Charging Control Rule-PCC Rule)解析及模板样例
内容 PCC规则定义 PCC规则运行 PCC规则模板 PCC规则定义 参考文档: 3gpp ts 23.203-be0 条款6.3 策略与计费控制规则(PCC Rule),即一系列相关信息与一系列相关 ...
- 常用Linux命令:mount/umount/blkid
一.mount:挂载命令 1.命令格式 mount [参数] [设备名称] [挂载点] 2.常用参数 -a :安装在/etc/fstab文件中列出的所有文件系统 -f :伪装mount,做出检 ...
- .net core MVC Filters 过滤器介绍
一.过滤器的优级依次介绍如下(逐次递减): Authorization Filter -> Resource Filter -> Acton Filter -> Exception ...