MapReduce格式与类型

MapReduce Types

  MapReduce是一个简单的数据处理模型,map与reduce的输入和输出类型都为key-value形式的键值对。

map: (K1, V1) → list(K2, V2)
reduce: (K2, list(V2)) → list(K3, V3)

  一般来讲,map的输入key与输出value类型(K1,V1)不同于map的输出类型(K2,V2).reduce的输入类型比如与map的输出类型保持一致,reduce的输出类型可能会有不同的形式(K3,V3)。下面是JAVA API:

public class Mapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT> {
  public class Context extends MapContext<KEYIN, VALUEIN, KEYOUT, VALUEOUT> {
    // ...
  }
  protected void map(KEYIN key, VALUEIN value, 
                     Context context) throws IOException, InterruptedException {
    // ...
  }
}

public class Reducer<KEYIN, VALUEIN, KEYOUT, VALUEOUT> {
  public class Context extends ReducerContext<KEYIN, VALUEIN, KEYOUT, VALUEOUT> {
    // ...
  }
  protected void reduce(KEYIN key, Iterable<VALUEIN> values,
                        Context context) throws IOException, InterruptedException {
    // ...
  }
}

  最终由context调用write()方法将key-value pairs输出

public void write(KEYOUT key, VALUEOUT value)
    throws IOException, InterruptedException

  Mapper与Reducer是两个不同的classes,分别具有不同的入参类型,Mapper的入参类型可能与Reducer的入参类型不同,比如Mapper的key的入参为LongWritable,reduce的为Text.

  这里有一点,如果在map阶段调用了combine方法,那么就与reduce的入参相同

map: (K1, V1) → list(K2, V2)
combine: (K2, list(V2)) → list(K2, V2)
reduce: (K2, list(V2)) → list(K3, V3)

  使用parition方法对中间结果的key与value进行操作时,将会返回parition的位置(index),parition将决定于排过序的key

public interface Partitioner<K2, V2> extends JobConfigurable {
  int getPartition(K2 key, V2 value, int numPartitions);
}

  默认的分区类型为HashPartitioner,由它决定着key属于哪个分区,每一个分区都属于一个reduce task,所以分区的个数决定了reduce tasks的个数

public class HashPartitioner<K, V> extends Partitioner<K, V> {


  public int getPartition(K key, V value,
                          int numReduceTasks) {
    return (key.hashCode() & Integer.MAX_VALUE) % numReduceTasks;
  }
}

  当你需要多个reduce tasks作业任务时,HashPartitioner就举足轻重了,因为map的结果将会传递给多个reduce,那么相同的key将会被分发到不同reduce task,大大提升了作业效率。那么reduce个数的决定了整个作业的并行度,有人会问,那map的个数呢,map的个数是由文件的block数目决定的,具体下面再说~

  那么reducer个数的把握将会是一门艺术- -增加reducer的个数相当于增加了并行度。

较小的文件与CombineFileInputFormat

  Hadoop的作业适用于较大的文件,原因在于FileInputFormat是split整个文件还是split单个文件,如果文件太小(这里指的是小于HDFS的block块大小)并且拥有很多这样的文件,那么就会增加打开文件的性能开销。同时,大量的小文件也会增加namenode的元数据的存储开销。

参考文献:《Hadoop:The Definitive Guide, 4th Edition》

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏小白鼠

Mybatis

从xml配置文件中读取配置,然后通过SqlSessionFactoryBuilder构建SqlSessionFactory实例(建造者模式)。SqlSessio...

2863
来自专栏JackieZheng

Hadoop阅读笔记(六)——洞悉Hadoop序列化机制Writable

  酒,是个好东西,前提要适量。今天参加了公司的年会,主题就是吃、喝、吹,除了那些天生话唠外,大部分人需要加点酒来作催化剂,让一个平时沉默寡言的码农也能成为一个...

2345
来自专栏程序员的SOD蜜

使用操作符重载,生成ORM实体类的SQL条件语句

ORM框架的一个不可或缺的功能就是根据实体类,生成操作数据库的SQL语句,这其中,最难处理的就是那些复杂的SQL条件比较语句。比如,有下面这样一个SQL语句: ...

23310
来自专栏me的随笔

Redis中的数据结构与常用命令

对于Redis的介绍这里只写一句:Redis是一种基于内存的高性能非关系型数据库,它以kye-value的形式来存储数据。

3333
来自专栏应兆康的专栏

Python Web - Flask笔记5

MySQL Workbench是一款专为MySQL设计的ER/数据库建模工具。它是著名的数据库设计工具DBDesigner4的继任者。你可以用MySQL Wor...

1851
来自专栏云霄雨霁

设计模式----单例模式

1540
来自专栏Web项目聚集地

手写一个Mybatis框架

在手写自己的Mybatis框架之前,我们先来了解一下Mybatis,它的源码中使用了大量的设计模式,阅读源码并观察设计模式在其中的应用,才能够更深入的理解源...

1102
来自专栏积累沉淀

干货--Hadoop自定义数据类型和自定义输入输出格式整合项目案例

正文开始前 ,先介绍几个概念 序列化 所谓序列化,是指将结构化对象转化为字节流,以便在网络上传输或写到磁盘进行永久存储。 反序列化 是指将字节流转回到结构化...

6516
来自专栏我叫刘半仙

原自己手写一个Mybatis框架(简化)

       继上一篇手写SpringMVC之后,我最近趁热打铁,研究了一下Mybatis。MyBatis框架的核心功能其实不难,无非就是动态代理和jdbc的操...

2K6
来自专栏java 成神之路

Java 序列化之 Externalizable

3256

扫码关注云+社区

领取腾讯云代金券