MapReduce:
是hadoop中的一个非常重要的组件,解决海量数据怎么计算的问题的组件
由来:谷歌论文 Map-Reduce
MapReduce到底是什么东西
-
从论文的角度分析:是一种思想
-
从技术的角度分析:是分布式计算框架
框架
软件框架(software framework),通常指的是为了实现某个业界标准或完成特定基本任务的软件组件规范,也指为了实现某个软件组件规范时,提供规范所要求之基础功能的软件产品。
规范
思想上的规范
map:最小化数据单元,并以键值对的形式传递到下一阶段。
reduce:接收上个阶段的数据,按照key相同合并数据,
以键值对的形式输出(可以写入文件)
举例:
原数据
1 宋宇 李飞 刘梦鸽 李心雨 郭浩
2 卢晶晶 蔡琛琛 郝加薪 宋新悦
3 宋红茹 吕鑫怡 卢航 宋单 卢昭昭
4 李湘议 王雪丽 刘甜鑫 郭梦迪
5 刘子酱 宋家毅 宋明星
**需求:**统计每个姓氏的个数
map阶段
原数据每行执行一次map
(宋,1) (李,1) (刘,1) (李,1) (郭,1)
(卢,1) (蔡,1) (郝,1) (宋,1)
(宋,1) (吕,1) (卢,1) (宋,1) (卢,1)
(李,1) (王,1) (刘,1) (郭,1)
(刘,1) (宋,1) (宋,1)
reduce阶段
reduce接收到数据,按key相同,value为一个可迭代对象
所有的map执行完毕之后,开始执行reduce。
(宋, 1,1,1,1,1,1)
(李, 1,1,1)
(刘, 1,1,1)
(郭, 1,1)
(卢, 1,1,1)
(蔡, 1)
(郝, 1)
(吕, 1)
(王, 1)
每个key执行一次reduce
key:宋 value:1,1,1,1,1,1
遍历循环当前key下的所有value数据求和
1+1+1+1+1+1=6
以键值对形式输出
(宋,6)
代码上的规范
-
Mapper类
实现map思想的代码,把数据划分成最小化数据单元,以键值对输出
-
Reducer类
实现reduce思想的代码,把key相同的value值进行操作,以键值对输出
-
Driver类
相当于程序的入口。指定一些泛型或者需要用到的数据信息。
举例:
wordCount 相当于java中的 hello world
**原数据:**一个文本文件内有多行数据,每行数据由多个单词组成,单词与单词之间由空格分隔。
**需求:**统计这个文件中每个单词出现的次数。
思路:
-
创建一个Mapper类,读取原数据。
-
每行执行一次map操作,把每行的字符串按空格分隔成单词数组
-
遍历这个单词数组,以(word,1)形式发送出去
-
重复执行2、3步骤,操作下一行数据。
-
创建一个Reducer类,接收map端的数据、
key相同,value是一个可迭代对象
-
在一个reduce操作中,对相应的value值求和(sum)
-
把统计好的结果,以(单词,sum)写入文件
-
重复 5、6、7 操作,执行下一个单词的统计
-
创建Driver类,指定所需内容
Mapper类
四个泛型
-
keyIn:输入的原数据key的泛型。
如果默认是文本文档,固定的LongWritable(代表偏移量)
-
valueIn:输入的原数据value的泛型
如果默认是文本文档,固定的Text(当前行的文本内容)
-
keyOut:map端的输出key的泛型,根据实际情况确定
-
valueOut:map端的输出value的泛型,根据实际情况确定
四个方法
-
setUp:执行mapper阶段开始仅执行一次的方法
一般用于初始化一些数据,不是必须使用
-
cleanUp:执行mapper阶段最后仅执行一次的方法
一般用于最后收尾工作,不是必须使用
-
map:每一行执行一次map方法,绝大多数都需要重写该方法
-
run:默认的执行逻辑,如果没有特殊情况,不需要重新
Reducer类
与Mapper类类似,区别:
-
map端的输出一定是reduce端的输入
-
reuduce端的输出类型与map无关
代码中的一些问题
-
关于输入路径
如果默认的执行环境是hdfs,但是使用的是本地路径,会出错
-
core-site.xml 删除或者改成file:///
-
conf.set(“fs.defaultFS”,“file:///”)
-
写路径的时候加上file:///
-
-
输出路径如果存在,报错
- 在执行之前手动删除这个目录
- 通过代码解决。
-
输入输出路径在代码中固定
如果把路径写死,一旦打成jar包就特别不容易修改,非常不方便,所以利用主方法的args参数来动态获取两个路径,输入和输出路径分别使用args[0]和args[1]来表示
run->editConfiguration->programArguments 传参,以空格分隔
如果读取一个目录下的所有文件,输入路径到目录即可,或者加/*
-
偏移量,setUp,cleanUp 的验证
-
能否把一个业务逻辑写在同一个类中
使用静态内部类实现
-
@TODO
把driver的方法封装成一个公共的方法
-
如果分隔数据的时候,分隔的内容不固定
使用正则表达式
asd 完全匹配 [asd] 匹配其中的任意一个字符 [a-de-g] 匹配这个范围中的任意一个字符 [^a-m] 除了这个范围以外的任意一个字符 \d [0-9] 一个数字 \w [0-9a-zA-Z_] 字母数字下划线 \s [ \t\n\r] 空白字符 相应的大写字符,表示非这个范围 ? 0-1次 * 0-n次 + 1-n次 {m} m次 {m,} m-多次 {m,n} m-n次 ^ 以...开头 $ 以...结尾