文档章节

MapReduce知识点详解二

simpler
 simpler
发布于 2014/05/19 11:53
字数 1876
阅读 143
收藏 1

序列化概念

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

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

Java序列化(java.io.Serializabl)

Hadoop序列化的特点

1.紧凑:高效使用存储空间。

2.快速:读写数据的额外开销小

3.可扩展:可透明地读取老格式的数据

4.互操作:支持多语言的交互

Hadoop序列化的作用

序列化在分布式环境的两大作用:进程间通信,永久存储。

Hadoop节点间通信。

bf81947f9a3a71970c687a87ea1369b0

自定义Writable类

class KpiWritable  implements Writable{
    int uppacknum;
    int downpacknum;
    int uppayload;
    int downpayload;
    
    public KpiWritable() {
        super();
    }
    
    public void set(String uppacknum, String downpacknum, String uppayload,
            String downpayload) {
        this.uppacknum = Integer.parseInt(uppacknum);
        this.downpacknum = Integer.parseInt(downpacknum);
        this.uppayload = Integer.parseInt(uppayload);
        this.downpayload = Integer.parseInt(downpayload);
    }
    public KpiWritable(int uppacknum, int downpacknum, int uppayload,
            int downpayload) {
        super();
        this.uppacknum = uppacknum;
        this.downpacknum = downpacknum;
        this.uppayload = uppayload;
        this.downpayload = downpayload;
    }
    
    public KpiWritable(String uppacknum, String downpacknum, String uppayload,
            String downpayload) {
        super();
        this.set(uppacknum, downpacknum, uppayload, downpayload);
    }
    @Override
    public void write(DataOutput out) throws IOException {
        out.writeInt(this.uppacknum);
        out.writeInt(this.downpacknum);
        out.writeInt(this.uppayload);
        out.writeInt(this.downpayload);
    }
    @Override
    public void readFields(DataInput in) throws IOException {
        this.uppacknum = in.readInt();
        this.downpacknum = in.readInt();
        this.uppayload = in.readInt();
        this.downpayload = in.readInt();
    }
    
    @Override
    public String toString() {
        return uppacknum +"\t"+ downpacknum +"\t"+uppayload +"\t"+downpayload;
    }
}

Writable

   1.write 是把每个对象序列化到输出流

   2.readFields是把输入流字节反序列化

实现WritableComparable.

Java值对象的比较:一般需要重写toString(),hashCode(),equals()方法

基于文件的存储结构

SequenceFile 无序存储

MapFile 会对key建立索引文件,value按key顺序存储

基于MapFile的结构有:

ArrayFile 像我们使用的数组一样,key值为序列化的数字

SetFile 他只有key,value为不可变的数据

BloomMapFile 在 MapFile 的基础上增加了一个 /bloom 文件,包含的是二进制的过滤表,在每一次写操作完成时,会更新这个过滤表。

SequenceFile

SequeceFile是Hadoop API提供的一种二进制文件支持。这种二进制文件直接将<key, value>对序列化到文件中。一般对小文件可以使用这种文件合并,即将文件名作为key,文件内容作为value序列化到大文件中。这种文件格式有以下好处:

支持压缩,且可定制为基于Record或Block压缩(Block级压缩性能较优)

本地化任务支持:因为文件可以被切分,因此MapReduce任务时数据的本地化情况应该是非常好的。

对key、value的长度进行了定义,(反)序列化速度非常快。

缺点是需要一个合并文件的过程,文件较大,且合并后的文件将不方便查看,必须通过遍历查看每一个小文件。

9b2b980e2959c4f996cafddb03fa5d4d

public static void main(String[] args) throws Exception{
        final Configuration conf = new Configuration();
        final FileSystem fs = FileSystem.get(new URI("hdfs://hadoop:9000/"), conf);
        //写操作
        final Writer writer = new SequenceFile.Writer(fs, conf, new Path("/sf"), LongWritable.class, Text.class);
        writer.append(new LongWritable(1), new Text("111"));
        IOUtils.closeStream(writer);
        //读操作
        final SequenceFile.Reader reader = new SequenceFile.Reader(fs, new Path("/sf"), conf);
        final LongWritable key = new LongWritable();
        final Text val = new Text();
        while (reader.next(key, val)) {
            System.out.println(key.get()+"\t"+val.toString());
        }
        IOUtils.closeStream(reader);
    }

MapFile

MapFile是排序后的SequenceFile,通过观察其目录结构可以看到MapFile由两部分组成,分别是data和index。

index作为文件的数据索引,主要记录了每个Record的key值,以及该Record在文件中的偏移位置。在MapFile被访问的时候,索引文件会被加载到内存,通过索引映射关系可迅速定位到指定Record所在文件位置,因此,相对SequenceFile而言,MapFile的检索效率是高效的,缺点是会消耗一部分内存来存储index数据。

需注意的是,MapFile并不会把所有Record都记录到index中去,默认情况下每隔128条记录存储一个索引映射。当然,记录间隔可人为修改,通过MapFIle.Writer的setIndexInterval()方法,或修改io.map.index.interval属性;

另外,与SequenceFile不同的是,MapFile的KeyClass一定要实现WritableComparable接口,即Key值是可比较的。

public static void main(String[] args) throws Exception{
        final Configuration conf = new Configuration();
        final FileSystem fs = FileSystem.get(new URI("hdfs://hadoop:9000/"), conf);
        //写数据
        final MapFile.Writer writer = new MapFile.Writer(conf, fs, "/aaa", Text.class, Text.class);
        writer.append(new Text("1"), new Text("aa"));
        IOUtils.closeStream(writer);
        //读数据
        final MapFile.Reader reader = new MapFile.Reader(fs, "/aaa", conf);
        final Text key = new Text();
        final Text val = new Text();
        while(reader.next(key, val)) {
            System.out.println(key.toString()+"\t"+val.toString());
        }
}

15298df427fcef8f3478af76560b782a

小文件存储

注意:使用MapFile或SequenceFile虽然可以解决HDFS中小文件的存储问题,但也有一定局限性,如:

1.文件不支持复写操作,不能向已存在的SequenceFile(MapFile)追加存储记录

2.当write流不关闭的时候,没有办法构造read流。也就是在执行文件写操作的时候,该文件是不可读取的

MapReduce输入的处理类

FileInputFormat:

FileInputFormat是所有以文件作为数据源的InputFormat实现的基类,

FileInputFormat保存作为job输入的所有文件,并实现了对输入文件计算splits的方法。至于获得记录的方法是有不同的子类——TextInputFormat进行实现的。

InputFormat

图片2

InputFormat 负责处理MR的输入部分.

有三个作用:

验证作业的输入是否规范.

把输入文件切分成InputSplit.

提供RecordReader 的实现类,把InputSplit读到Mapper中进行处理.

InputSplit

◆   在执行mapreduce之前,原始数据被分割成若干split,每个split作为一个map任务的输入,在map执行过程中split会被分解成一个个记录(key-value对),map会依次处理每一个记录。

◆   FileInputFormat只划分比HDFS block大的文件,所以FileInputFormat划分的结果是这个文件或者是这个文件中的一部分.               

◆   如果一个文件的大小比block小,将不会被划分,这也是Hadoop处理大文件的效率要比处理很多小文件的效率高的原因。

◆    当Hadoop处理很多小文件(文件大小小于hdfs block大小)的时候,由于FileInputFormat不会对小文件进行划分,所以每一个小文件都会被当做一个split并分配一个map任务,导致效率底下。

 例如:一个1G的文件,会被划分成16个64MB的split,并分配16个map任务处理,而10000个100kb的文件会被10000个map任务处理。  

TextInputFormat

◆  TextInputformat是默认的处理类,处理普通文本文件。

◆  文件中每一行作为一个记录,他将每一行在文件中的起始偏移量作为key,每一行的内容作为value。

◆  默认以\n或回车键作为一行记录。

◆  TextInputFormat继承了FileInputFormat。

底层架构

图片3

其他输入类

◆    CombineFileInputFormat

         相对于大量的小文件来说,hadoop更合适处理少量的大文件。

         CombineFileInputFormat可以缓解这个问题,它是针对小文件而设计的。

◆    KeyValueTextInputFormat

         当输入数据的每一行是两列,并用tab分离的形式的时候,KeyValueTextInputformat处理这种格式的文件非常适合。

◆    NLineInputformat 
         NLineInputformat可以控制在每个split中数据的行数。

◆    SequenceFileInputformat 

         当输入文件格式是sequencefile的时候,要使用SequenceFileInputformat作为输入。

Hadoop的输出处理类

TextOutputformat

       默认的输出格式,key和value中间值用tab隔开的。

◆    SequenceFileOutputformat

       将key和value以sequencefile格式输出。

◆    SequenceFileAsOutputFormat

       将key和value以原始二进制的格式输出。

◆    MapFileOutputFormat

       将key和value写入MapFile中。由于MapFile中的key是有序的,所以写入的时候必须保证记录是按key值顺序写入的。

◆    MultipleOutputFormat

        默认情况下一个reducer会产生一个输出,但是有些时候我们想一个reducer产生多个输出,MultipleOutputFormat和MultipleOutputs可以实现这个功能。


© 著作权归作者所有

simpler
粉丝 25
博文 44
码字总数 40338
作品 0
成都
程序员
私信 提问
大数据经典学习路线(及供参考)之 一

1.Linux基础和分布式集群技术 学完此阶段可掌握的核心能力: 熟练使用Linux,熟练安装Linux上的软件,了解熟悉负载均衡、高可靠等集群相关概念,搭建互联网高并发、高可靠的服务架构; 学完此...

柯西带你学编程
2018/05/22
0
0
大数据hadoop是什么?初学者如何进行系统学习?

大数据的火爆程度在不断的增加,似乎一个行业不和大数据相对接就会显得很“LOW”。大数据行业的薪资水平越来越高,决定了更多的人纷纷学习大数据,hadoop作为大数据的一个核心自然就是学习的...

hainiubuluo
2018/05/25
0
0
大数据教程(10.7)Mapreduce的其他补充(计数器、多job串联、参数优化等)

上一篇文章分析了自定义inputFormat(小文件合并)的实现,在此博主将继续Mapreduce的其他补充(计数器、多job串联、参数优化等)内容的分享。 一、计数器应用 在实际生产代码中,常常需要将...

em_aaron
2018/12/30
41
0
如何分布式运行mapreduce程序

如何分布式运行mapreduce程序 一、 首先要知道此前提 若在windows的Eclipse工程中直接启动mapreduc程序,需要先把hadoop集群的配置目录下的xml都拷贝到src目录下,让程序自动读取集群的地址后...

Zero零_度
2015/09/06
261
0
大数据教程(6.5)hadoop shell命令操作&mapreduce程序运行初体验

上一篇文章,博主为大家分享了hadoop的安装以及集群的启动,本篇博客将带领小伙伴们一起来感受下hadoop命令和Linux命令的使用有什么不同。 一、首先,启动hadoop集群,执行脚本sh start-dfs....

em_aaron
2018/11/03
441
0

没有更多内容

加载失败,请刷新页面

加载更多

应急广播户户通平台

一、平台概述 应急广播户户通平台为软硬一体化广播服务解决方案。实现了应急广播、视音频及图片文字信息、调频及数字广播FM、天气预报信息接收功能,以及视音频播放、智能机器人、电子日历等...

neocean
29分钟前
39
0
如何为Apache 2.2启用mod_rewrite

我已经在我的Vista机器上安装了新的Apache 2.2,一切正常,除了mod重写。 我没有注释 LoadModule rewrite_module modules/mod_rewrite.s 但是我的重写规则都没有,即使是简单的重写规则 Re...

javail
35分钟前
23
0
移除Python unicode字符串中的重音符号的最佳方法是什么?

我在Python中有一个Unicode字符串,我想删除所有的重音符号(变音符号)。 我在网上发现了一种用Java实现此目的的优雅方法: 将Unicode字符串转换为长规范化格式(带有单独的字母和变音符号)...

技术盛宴
51分钟前
48
0
ActiveMQ学习之SpringBoot整合ActiveMQ------>主题生产者和消费者

一、pom <!--聚合工程集成关系--> <!--统一整合第三方框架依赖信息--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</a......

冥焱
今天
75
0
两周自制脚本语言-第11天 优化变量读写性能

第11天 优化变量读写性能 以变量值的读写为例,向读者介绍基于这种理念的语言处理器性能优化方式。 11.1 通过简单数组来实现环境 假如函数包含局部变量x与y,程序可以事先将x设为数组的第0个...

果汁分你一半
今天
52
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部