聊聊MapReduce处理过程中的数据类型与数据格式

MapReduce处理过程总览

对于MP的处理过程我想大部分人都已经知道了其原理,思路不难,这是肯定的,但是整个过程中需要考虑的细枝末节的点还挺多的,MP的输入输出格式就是其中的一点,那本文就带领大家看看MP中的格式设置问题。

map函数,起到了如下的转换作用:map:(k1,v1)—>list(k2,v2)

reduce 函数,则起到了这样的格式转换作用:reduce:(k2,list(v2))—>list(k3,v3)

怎么,你说你看不懂?那看来你还是没有对mapreduce的过程有所理解,看看这幅图,不需要解释,你就明白上面的格式转化是什么意思了:

上面这幅图出自我的另外一篇博文:编写自己的第一个Hadoop实例,如果你设置了combiner函数,那么中间的格式转化将会是这个样子:


  1. map:(k1,v1)—>list(k2,v2)  
  2. combiner:(k2,list(v2))—>list(k2,v2)  
  3. reduce:(k2,list(v2))—>list(k3,v3) 

是的,没错,combiner从功能上来讲就是一个reducer,它的存在大大减小了reducer的压力。

partition函数对中间结果(k2,v2)进行处理,返回一个索引值,即分区号


  1. partition:(k2,v2)—>integer 

在前面的文章中,也就是我的博客:MapReduce输入分片详解中,我提到了分片是与map函数数量相等,同时它不是咱们想的那样是一个实物分片,在程序上输入分片在java中表现为InputSplit接口


  1. public abstract class InputSpilt{ 
  2.        public abstract long getLength(); 
  3.        public abstract String[] getLoacations(); 

存储位置供mapreduce使用,以便使map任务尽量在分片附近。分片大小是用来对分片进行排序,以便优先处理最大的最大分片,从而最小化时间。InputSplit不需要MR开发人直接处理,而是由InputFormat创建。

客户端通过调用InputFormat的getSplits()计算分片,然后将他们送到application master(或jobtracker),am使用存储位置信息调度map任务在tasktracker上处理这些分片数据。map任务把输入分片传递给InputFormat的getRecordReader()方法来获得这个分片的RecordReader。RecordReader类似迭代器,对map任务进行迭代,来生成键/值对,然后传递给map函数。也就是说InputFormat不仅仅可以计算分片,进行数据分割,还可以对分片进行迭代,也就是说获得分片的迭代器,所有有关分片的操作都由InputFormat来支持,可见其强大性。

输入格式

那既然InputFormat这么牛逼,那我们就来看看这个接口到底包含了什么,先来看看下面这张图:

FileInputFormat类

FileInputFormat是所有文件作为数据源的InputFormat的实现类,主要有两个功能:指定输入文件位置和输入文件生成分片的实现代码段。换句话说,它并不生成分片,只是返回文件位置,并且实现了分片算法。

FileInputFormat指定输入路径


  1. addInputPath(Job job,Path path);  
  2. addInputPaths(Job job,String paths);  
  3. setInputPaths(Job job,Path ...inputPaths); 

可以添加一个路径或者多个路径,其中setInputPaths是以此设定完成的路径列表。其中路径可以是一个文件、一个目录、或者一个glob(通配,通过通配符来获取路径),当路径是一个目录的时候表示包含目录下的所有文件。当目录中包含目录的时候,这个目录也会被解释称文件,所以会报错。可以通过使用一个文件glob或者一个过滤器根据命名模式限定选择目录中的文件。还可以通过设置属性mapred.input.dir.recursive为true强制对目录进行递归读取。如果需要排除目录中的个别文件,可以通过setInputPathFileter()设置一个过滤器来进行过滤,如果不设置过滤器,也会有默认的过滤器排除隐藏文件(以.和_开头的)。路径和过滤器业可以使用配置文件进行配置:mapred.input.dir和mapred.input.path.Fileter.class

小文件处理

(小文件是指比HDFS块小很多)在Hadoop中使用小文件的弊端:

(1)、增加map开销,因为每个分片都要执行一次map任务,map操作会造成额外的开销

(2)、MapReduce处理数据的最佳速度就是和集群中的传输速度相同,而处理小文件将增加作业的寻址次数

(3)、浪费namenode的内存

解决方法:

使用SequenceFile将这些小文件合并成一个大文件或多个大文件:将文件名作为键,文本内容作为值。

但是如果HDFS中已经存在的大批小文件,可以使用CombinerFileInputFormat。

CombinerFileInputFormat把多个文件打包成一个文件以便每个mapper能够处理更过的数据

避免切分

有时候不需要将文件进行切分,mapper完整处理每个输入文件。例如检查一个文件的所有记录是否有序。

可以通过设置最小分片大小大于要处理的文件。第二种就是使用FileInputFormat的具体子类,并且重载isSplitable()方法,把返回值设置为false。

mapper中的信息

通过调用Mapper中的Context的getInputSolit()返回一个InputSplit,如果使用的是FileInputFormat,则可以强转为FileSplit,然后用此访问正在输入文件的路径getPath(),分片开始处的字节偏移量,getLength()分片的长度。

TextInputFormat

文本输入是默认的InputFormat,每条记录是一行输入,键是LongWritable类型,存储该记录在整个文件的字节偏移量。值是该行的内容,不包括终止符(回车、换行等),它被打包成Text对象。

KeyValueTextInputFormat

当文件中的每一行是一个键/值对,使用某个分界符进行分割,如制表符。可以通过mapreduce.input.keyvaluelinerecordreader.key.value.seperator属性来指定分隔符。默认是一个制表符。其中这个键是分隔符前的文本,值是分隔符后的文本,其类型都是Text类型。如:


  1. line1:this is line1 text  
  2. line2:this is line2 text 

则被分为两条记录,分别是:


  1. (line1,this is line1 text) 
  2. (line2,this is line2 text) 

NLineInputFormat

在TextInputFormat和KeyValueTextInputFormat中,每个mapper收到的输入行数并不确定,行数取决于输入分片的大小和行的长度。如果希望mapper收到固定行数的输入,可以使用NLineInputFormat作为InputFormat。与TextInputFormat奕扬,键是文件中行的字节偏移量,值是行的内容。

N是每个mapper收到的输入行数,默认是1。可以通过mapreduce.input.lineinputformat.linespermap属性设置。如:

On the top of the Crumetty Tree

The Quangle Wangle sat,

But his face you could not see,

On account of his Beaver Hat.

当N为2的时候,每个输入分片包含两行。

(0,On the top of the Crumetty Tree)

(33,The Quangle Wangle sat,)

另一个mapper则收到后两行

(57,But his face you could not see,)

(89,On account of his Beaver Hat.)

StreamInputFormat

当解析XMl文件的时候可以使用StreamInputFormat,将stream.recordreader.class属性设置为org.apache.Hadoop.Streaming.StreamXmlRecordReader使用StreamXmlRecordReader类。具体实现(没用过)可以查看该类官方文档

SequenceFileInputFormat

Hadoop顺序文件格式存储二进制的键/值对的序列。当需要使用顺序文件作为MapReduce的输入时,应该使用SequenceFileInputFormat。键和值由顺序文件指定,只需要保证map输入的类型匹配。

SequenceFileAsTextInputFormat

SequenceFileAsTextInputFormat是SequenceFileInputFormat的变体,将顺序文件的键和值转化为Text对象。

SequenceFileAsBinaryInputFormat

SequenceFileAsBinaryInputFormat是SequenceFileInputFormat的一种变体,获取顺序文件的键和值作为二进制对象。

MutipleInputs

一个MapReduce作业可能由多个输入文件,但所有文件都由同一个InputFormat和同一个mapper来处理。但是数据格式却有所不同,需要对不同的数据集进行连接操作。可以使用MutipleInputs类处理

DBInputFormat

DBInputFormat用于使用JDBC从关系数据库中读取数据。需要注意在数据库中运行太多mapper读取数据,可能会使数据库受不了,所以一般使用DBInputFormat加载少量数据。可以现将数据导入到HDFS中,一般将关系性数据库中数据导入到HDFS中可以使用Sqoop

输出格式

TextOutputFormat

默认的输出模式TextOutputFormat,每条记录写为一行。键和值是任意的,因为TextOutputFormat都要将其toString()转换为字符串。键值默认使用制表符分割,可以使用mapreduce.output.textoutputformat.separator属性改变分割符

SequenceFileOutputFormat

将输出写为一个顺序文件,当输出需要作为后续的MapReduce输入的时候,这种输出非常合适,因为它格式紧凑,容易被压缩。

SequenceFileAsBinaryOutputFormat

SequenceFileAsBinaryOutputForamt与SequenceFileAsBinaryInputFormat对应,将输出的键和值作为二进制格式写到SequenceFile容器中。

MultipleOutputFormat

有时候可能需要将每个reduce输出多个文件,可以使用MutltipleOutputFormat。

LazyOutputFormat

延迟输出,他是封装输出格式,可以保证指定分区第一条记录输出时才真正创建文件。

本文作者:牧师-Panda

来源:51CTO

时间: 2024-11-10 00:28:09

聊聊MapReduce处理过程中的数据类型与数据格式的相关文章

SQLServer---查询过程中的数据类型转化

SQLServer---查询过程中的数据类型转化            前两天在维护某市人才服务中心的人事档案管理系统的时候,发现了这个一个问题新的档案编号规则是日期+已有档案最大编号+1(六位,不足六位在中间补零)(((CONVERT([varchar](9),[createTime],(112))+'')+right((100000000000.)+[num],(6))))例如:20150511007841.说实话真的不清楚当时为什么会用最大编号,而不是用总记录数+1(不存在删除数据),接下

交互设计经验:设计过程中存在太多的矛盾

文章描述:交互设计经验:设计过程中存在太多的矛盾. 在产品团队中经常听到有人表态:"我们要做简洁的用户界面",同时又有另外一种声音传来:"我们要做功能强大的产品".乍一听,简洁意味着用户界面控件精炼,然而少数的交互方式如何表达各类强大的功能?反之,强大意味着功能丰富强劲,必然拥有错综复杂的联系,如何让其界面保持简洁?两者似乎无法共存,这让我突然想到自相矛盾的故事,楚国商人夸耀自己的矛锐利万分,同时自己的盾又坚固无比, "以子之矛,陷子之盾,何如?"

网页设计师页面设计过程中也要注意页面性能

一名网页设计师在做具体设计的时候应该考虑的问题有哪些?业务,产品,信息结构,交互,视觉--别忘了还有页面性能.我所崇尚的其实一直都是小作坊似的创业团队协作开发模式,大伙儿能快速沟通,就算设计师没关注到页面性能这一点,前端同学也能迅速提醒他,因为他俩就无时无刻不在一起.而现在在标准项目流程中,大家的沟通成本成倍增加了,除非是与世隔绝的闭关(就算是闭关,前端同学多半也在陪着开发),前端同学很难在页面设计过程中就和设计师沟通页面性能的问题. 页面性能不仅仅是前端同学的问题 页面性能的重要性不再赘述,就

从错误中汲取经验:打造Buffer过程中所学到的

Buffer是一款帮助你在Twitter.Facebook等平台上更高效的发布内容的应用,到目前我们已经有超过50万的用户了.两年前刚刚开始打造这个产品的时候,我们就已经做好了充分的思想准备去面对各种挑战,包括设计开发过程中会遇到的障碍以及可能犯的错误. 我们始终觉得,在项目当中犯错是在所难免的;只要能够从中学到一些东西,这些错误就能引导我们向正确的方向前进.从某种程度上讲,将我们的产品一点点推向成功的也许正是一路上所犯下的那些错误. 重要的设计原则 在开始讨论我们从错误当中学习到的那些经验之前

背水一战 Windows 10 (21) - 绑定: x:Bind 绑定, x:Bind 绑定之 x:Phase, 使用绑定过程中的一些技巧

原文:背水一战 Windows 10 (21) - 绑定: x:Bind 绑定, x:Bind 绑定之 x:Phase, 使用绑定过程中的一些技巧 [源码下载] 背水一战 Windows 10 (21) - 绑定: x:Bind 绑定, x:Bind 绑定之 x:Phase, 使用绑定过程中的一些技巧 作者:webabcd 介绍背水一战 Windows 10 之 绑定 x:Bind 绑定 x:Bind 绑定之 x:Phase 使用绑定过程中的一些技巧 示例1.演示 x:Bind 绑定的相关知识点

Hadoop-2.8.0集群搭建、hadoop源码编译和安装、host配置、ssh免密登录、hadoop配置文件中的参数配置参数总结、hadoop集群测试,安装过程中的常见错误

25.集群搭建 25.1 HADOOP集群搭建 25.1.1集群简介 HADOOP集群具体来说包含两个集群:HDFS集群和YARN集群,两者逻辑上分离,但物理上常在一起 HDFS集群: 负责海量数据的存储,集群中的角色主要有NameNode / DataNode YARN集群: 负责海量数据运算时的资源调度,集群中的角色主要有 ResourceManager /NodeManager 25.1.2服务器准备 本案例使用虚拟机服务器来搭建HADOOP集群,所用软件及版本: ü Vmware 11.

MapReduce的过程(2)

MapReduce的编程思想(1) MapReduce的过程(2) 1. MapReduce从输入到输出 一个MapReduce的作业经过了input.map.combine.reduce.output五个阶段. 其中combine阶段不一定发生,map输出的中间结果被分发到reduce的过程称为shuffle(数据混洗). shuffle阶段会发生copy(复制)和sort(排序). Reduce任务默认在Map任务数量完成5%才开始启动. 2. input HDFS上的文件作为MapRedu

【白鳝的创业故事】创业过程中的机会与选择

今天早上起得有点晚,刚到公司楼下,就接到了王总的电话,让我准备一下,马上去趟北京.我说那我马上回家拿两件衣服.王总说不用了,我们去北京参加一个商务会晤,如果顺利的话,我们可以坐晚班飞机回来.我刚刚走进办公室,王总就拎着包走了进来说:"老白,准备好了吗?我们马上出发".就这样,我懵懵懂懂的跟着王总开始了这个改变我一生的旅程. 我们乘坐10点40分的航班飞往北京,下午2点的时候,我和王总就赶到了新世纪酒店.在飞机上,我大概了解了此行的目的,这次到北京是和Pansky的彭先生谈换股并购的事情

java中的数据类型的相互转换

问题描述 java中的数据类型的相互转换 我在学习java中的过程中,遇到这样一个问题 byte,char,short这三种数据进行运算的结果是int型 但是如果是float和int运算的话,结果是float型 我查了下,是java在运算时,会先转换成容量大的类型 而在java中,最大的容量是double,下来是float,然后是int,但是我又看了这几个类型的范围,int的范围比float大多了,这是怎么回事 难道所谓的容量大小和表示范围不一样吗? 在下先谢过各位了, 解决方案 浮点型和整形相