MapReduce的序列化

  序列化(Serialization)是指把结构化对象转化为字节流。

  反序列化(Deserialization)是序列化的逆过程。把字节流转为结构化对象。

  当要在进程间传递对象或持久化对象的时候,就需要序列化对象成字节流,反之当要将接收到或从磁盘读取的字节流转换为对象,就要进行反序列化。Java 的序列化(Serializable)是一个重量级序列化框架,一个对象被序列化后,会附带很多额外的信息(各种校验信息,header,继承体系…),不便于在网络中高效传输;所以,hadoop 自己开发了一套序列化机制( Writable),精简,高效。不用像 java 对象类一样传输多层的父子关系,需要哪个属性就传输哪个属性值,大大的减少网络传输的开销。

  Writable是Hadoop的序列化格式,hadoop定义了这样一个Writable接口。一个类要支持可序列化只需实现这个接口即可。

public class BeanDemo implements Writable {

    private long id;
private String desc; //一定要有无参构造,不然反序列化的时候会报错
public BeanDemo() {
} public BeanDemo(long id, String desc) {
this.id = id;
this.desc = desc;
} /**
* 序列化方法
*
* @param out
* @throws IOException
*/
@Override
public void write(DataOutput out) throws IOException {
out.writeLong(id);
out.writeUTF(desc);
} /**
* 反序列化方法
*
* @param in
* @throws IOException
*/
@Override
public void readFields(DataInput in) throws IOException {
this.id = in.readLong();
this.desc = in.readUTF();
}
}

MapReduce的排序

如果我们需要用某个我们自定义的JavaBean中的某个字段进行结果的排序,那么就需要把这个JavaBean放到key中传输,因为在MapReduce的过程中一定会对key进行排序,而且我们可以自己定义排序的方式,一旦我们需要把JavaBean放到key中传输的话,那么这个JavaBean需要实现Comparable接口的compareTo方法:

public class BeanDemo implements Writable, Comparable<BeanDemo> {

    private long id;
private String desc; //一定要有无参构造,不然反序列化的时候会报错
public BeanDemo() {
} public BeanDemo(long id, String desc) {
this.id = id;
this.desc = desc;
} /**
* 序列化方法
*
* @param out
* @throws IOException
*/
@Override
public void write(DataOutput out) throws IOException {
out.writeLong(id);
out.writeUTF(desc);
} /**
* 反序列化方法
*
* @param in
* @throws IOException
*/
@Override
public void readFields(DataInput in) throws IOException {
this.id = in.readLong();
this.desc = in.readUTF();
} /**
* @param o
* @return
*/
@Override
public int compareTo(BeanDemo o) {
//按照id倒序排
//虽然this.id 比o.id 大 依然返回-1 认为小 由于排序规则谁大谁在后 所以就形成了倒序
return this.id > o.id ? -1 : 1;
}
}

这样得出的结果就以id倒序排序了。

MapReduce的分区

如果有一种需求,需要将结果根据规则分别写到不同的文件中去,那么我们就需要多个reduce来执行,既然需要多个reduce那么就需要多个分区,让每个reduce拉取属于自己分区的数据进行操作和输出

Mapreduce 中会将 map 输出的 kv 对,按照相同 key 分组,然后分发给不同的 reducetask。
默认的分发规则为:根据 key 的 hashcode%reducetask 数来分发;
所以:如果要按照我们自己的需求进行分组,则需要改写数据分发(分组)组件 Partitioner,自定义一个 CustomPartitioner 继承抽象类:Partitioner,然后在job 对象中,设置自定义 partitioner: job.setPartitionerClass(CustomPartitioner.class)。

案例:以 上一篇的简单案例 为基础,在此基础上实现:a开头的写到一个文件中,b开头的写到一个文件中,其他的写到另外一个文件中

首先编写Partitioner类:

public class WordPartitioner extends Partitioner<Text, IntWritable> {

    public static HashMap<String, Integer> map = new HashMap<String, Integer>();

    static {
map.put("a", 0);
map.put("b", 1);
} @Override
public int getPartition(Text key, IntWritable intWritable, int numPartitions) {
//获取每个词的第一个字母 在 map中对应的数字
Integer code = map.get(key.toString().substring(0, 1));
if (code != null) {
return code;
}
return 2;
}
}

修改执行类,修改reduce个数和添加自定义分区组件:

public class WordCountRunner {
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration(); //指定mr采用本地模式运行 本地测试用
conf.set("mapreduce.framework.name", "local"); //使用job构建本次mr程序
Job job = Job.getInstance(conf); //指定本次mr程序运行的主类
job.setJarByClass(WordCountRunner.class); //指定本次mr程序的mapper reducer
job.setMapperClass(WordCountMapper.class);
job.setReducerClass(WordCountReducer.class); //指定本次mr程序map阶段的输出类型
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class); //指定本次mr程序reduce阶段的输出类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class); //设置使用几个Reduce执行 要和下面的WordPartitioner内的分区数相同
job.setNumReduceTasks(3);
//设置自定义分区组件
job.setPartitionerClass(WordPartitioner.class); //指定本次mr程序处理的数据目录 输出结果的目录
// FileInputFormat.setInputPaths(job, new Path("/wordcount/input"));
// FileOutputFormat.setOutputPath(job, new Path("/wordcount/output")); //本地测试用
FileInputFormat.setInputPaths(job, new Path("D:\\wordcount\\input"));
FileOutputFormat.setOutputPath(job, new Path("D:\\wordcount\\output"));//输出的文件夹不能提前创建 否则会报错 //提交本次mr的job
//job.submit(); //提交任务 并且追踪打印job的执行情况
boolean b = job.waitForCompletion(true);
System.exit(b ? 0 : -1);
}
}

Hadoop之MapReduce(二)序列化,排序及分区的更多相关文章

  1. Hadoop学习笔记: MapReduce二次排序

    本文给出一个实现MapReduce二次排序的例子 package SortTest; import java.io.DataInput; import java.io.DataOutput; impo ...

  2. (转)MapReduce二次排序

    一.概述 MapReduce框架对处理结果的输出会根据key值进行默认的排序,这个默认排序可以满足一部分需求,但是也是十分有限的.在我们实际的需求当中,往往有要对reduce输出结果进行二次排序的需求 ...

  3. 详细讲解MapReduce二次排序过程

    我在15年处理大数据的时候还都是使用MapReduce, 随着时间的推移, 计算工具的发展, 内存越来越便宜, 计算方式也有了极大的改变. 到现在再做大数据开发的好多同学都是直接使用spark, hi ...

  4. Hadoop MapReduce 二次排序原理及其应用

    关于二次排序主要涉及到这么几个东西: 在0.20.0 以前使用的是 setPartitionerClass setOutputkeyComparatorClass setOutputValueGrou ...

  5. MapReduce二次排序

    默认情况下,Map 输出的结果会对 Key 进行默认的排序,但是有时候需要对 Key 排序的同时再对 Value 进行排序,这时候就要用到二次排序了.下面让我们来介绍一下什么是二次排序. 二次排序原理 ...

  6. mapreduce二次排序详解

    什么是二次排序 待排序的数据具有多个字段,首先对第一个字段排序,再对第一字段相同的行按照第二字段排序,第二次排序不破坏第一次排序的结果,这个过程就称为二次排序. 如何在mapreduce中实现二次排序 ...

  7. MapReduce 二次排序

    默认情况下,Map 输出的结果会对 Key 进行默认的排序,但是有时候需要对 Key 排序的同时再对 Value 进行排序,这时候就要用到二次排序了.下面让我们来介绍一下什么是二次排序. 二次排序原理 ...

  8. 关于MapReduce二次排序的一点解答

    上一篇博客说明了怎么自定义Key,而且用了二次排序的例子来做测试,但没有详细的说明二次排序,这一篇说详细的说明二次排序,为了说明曾经一个思想的误区,特地做了一个3个字段的二次排序来说明.后面称其为“三 ...

  9. java mapreduce二次排序

    原文链接: https://www.toutiao.com/i6765808056191156748/ 目的: 二次排序就是有下面的数据 a 3 a 1 a 100 c 1 b 2 如果只按照abc排 ...

  10. Hadoop(18)-MapReduce框架原理-WritableComparable排序和GroupingComparator分组

    1.排序概述 2.排序分类 3.WritableComparable案例 这个文件,是大数据-Hadoop生态(12)-Hadoop序列化和源码追踪的输出文件,可以看到,文件根据key,也就是手机号进 ...

随机推荐

  1. eclipse mars4.5安装hibernate开发环境

    在安装hibernate插件过程中遇到下面前三张图片所示的现象是没关系的,只要最后能看到第四张图的结果就说明安装成功,我一开始不知道走了好多弯路.我用的eclipse mars4.5,采用了在线安装的 ...

  2. 利用selenium webdriver点击alert提示框

    在进行元素定位时常常遇到这样的alert框: 那么该如何定位并点击确定或取消按钮呢?stackoverflow上找到了这个问题的答案. OK, Show you the code: driver.fi ...

  3. linux TCP Fast Open开启和测试

    linux上要开启TCP Fast Open,内核版本至少为3.7.0, 且需要设置 /proc/sys/net/ipv4/tcp_fastopen 为3. 开启后,如果有连接进来,使用如下命令查看: ...

  4. beego数据输出

    beego数据输出   概览 直接输出字符串 模板数据输出 静态模板数据输出 动态模板数据输出 json格式数据输出 xml格式数据输出 jsonp调用 概览 直接输出字符串 通过beego.Cont ...

  5. 10.排序数组中和为给定值的两个数字[Find2NumbersWithGivenSum]

    [题目] 输入一个已经按升序排序过的数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字.要求时间复杂度是O(n).如果有多对数字的和等于输入的数字,输出任意一对即可. 例如输入数组1 ...

  6. SGU 507 Treediff

    这个题目  其实可以暴力  用两个 set 合并: 每次放进去一个元素只要找到这个元素第一个比他大的元素和最后一个比他小的元素:然后更新最优值: 证明为什么不会超时:  假如最后集合的小的为 S1,大 ...

  7. linux下安装boost

    linux平台下要编译安装除gcc和gcc-c++之外,还需要两个开发库:bzip2-devel 和python-devel,因此在安装前应该先保证这两个库已经安装:#yum install gcc ...

  8. pmm监控页面502

    我们知道pmm主要使用的是 普罗米修斯采集和grafana日志统计显示. 最近为硬盘扩过一次容量,主要是docker使用的,我的pmm是跑在docker上的,但是重启后pmm的debug日志下载502 ...

  9. vuecli3修改项目启动端口

    工作中可能存在启动多个项目的时候,默认端口号会被占,导致启动错误,这种情况下只要把要启动的项目的端口号换掉启动未用的端口就可以了,具体实现如下: vuecli3中的端口文件存放目录为:node_mod ...

  10. apt安装工具

    apt-cache search package 搜索包 apt-cache show package 获取包的相关信息,如说明.大小.版本等 sudo apt-get install package ...