MapReduce的代码实现过程分析
需求:使用mapreduce实现文件a.txt中不同单词出现的次数
map之前:
1):map处理之前的数据我们称为map<k1,v1>
例:
map<k1,v1> 在这里我们一次读取一行,行号就相当于k1,行的所有内容相当于v1
map阶段:
继承org.apache.hadoop.mapreduce.Mapper
重写map
2)将map<k1,v1>读取、解析并将结果存到map<k2,v2>中
例:
将文件(节点)中的数据,一次读取一行,将以空格或制表符连接的单词解析处理,然后以map<单词,次数>的形式存取。返回的数据我们称为map<k2,v2>
注:在这里所有单词的次数都是1(如果一行中有两个相同的单词,也是分别存储两次)
3):调用框架中的方法将map<k2,v2>按照k2分组并根据k2排序,我们将返回结果称为map<k2,v2s> ,其中v2s代表v2的集合。
注:这一步由框架完成
由于map阶段的数据很多,不可能把map<k2,v2s>一个一个的return出来,因为return一个之后,其他的就不能返回了,所以需要将结果存到一个上下文中,context.write(),
reduce阶段:
继承org.apache.hadoop.mapreduce.Reducer
重写:reduce
4):将map<k2,v2s>作为参数传入reduce中,reduce对相同k2的v2s进行汇总,返回结果我们称为map<k3,v3>
例:
遍历v2s将v2s相加,最终得到map<单词,总次数>的集合
网络之间数据的传输都是通过序列化来完成的,由于map和reduce的传输过程中有很多大文件,而java的序列化过程会使文件变得更大,这样对传输效率影响很大,所以hadoop自己实现了序列化。
java序列化的不足:
1.不精简。附加信息多。不大适合随机访问。
2.存储空间大。递归地输出类的超类描述直到不再有超类(即如果要序列化一个类,那么这个类的父类,父类的父类……等都需要序列化过去)。序列化图对象,反序列化时为每个对象新建一个实例。相反。Writable对象可以重用。
3.扩展性差。而Writable方便用户自定义
hadoop的序列化:
1):格式
Writable
2):特点:(Writable序列化的都是java的基本类型)
紧凑:高效使用存储空间。
快速:读写数据的额外开销小
可扩展:可透明地读取老格式的数据
互操作:支持多语言的交互