MapReduce 的类型与格式
默认的输入格式是
TextlnputFormat
,它产生的键类型是
LongW
table( 文件中每行中开始的偏移量值),值类型是
Text(
文本行)。这也解释了最后输出的整数的
含义:它们是行偏移量。map 任务是由 MapRunner 负责运行的, MapRunner MapRunnable 的默认实现,它顺序地为每一条记录调用一次 Mapper map() 方法。
默认的输出格式是
Tex
tOutputFormat
,它将键和值转换成字符&1井用
Tab 进行分隔,然后一条记录一
行地进行输出。
Streaming 应用可以决定分隔符,该分隔符用于通过标准输入把键/值对转换为一串比特值发送到
map
reduce 函数,
当
map
reduce 输出结果键/值对时,也需要一个可配置的分隔符来进行分隔。
一个输入分片
(split)
就是由单个
map 处理的输入块,一个输入分片可以对应于一个表上的若干行,InputSplit 包含一个以字节为单位的长度和一组存储位置(即一组主机名)。注意,一个分片井不包含数据本身,而是指向数据的引用 (reference) 。存储位置供 MapReduce 系统使用以便将 map 任务尽量放在分片数据附近,而长度用来排序分片,以便优先处理最大的分片,从而最小化作业运行时间。
MapReduce
应用开发人员井不需要直接处理
InputSpli
t ,因为它是由InputFormat
创建的。
InputFormat
负责产生输入分片井将它们分割成记录。FilelnputFormat 是所有使用文件作为其数据掘的 InputFormat 实现的基类 。它提供了两个功能:一个定义哪些文件包含在一个作业的输入中,一个为输入文件生成分片的实现。把分片分割成记录的作业由其子类来完成。
FilelnputFormat 类的输入分片
FilelnputFormat
只分割大文件。这里的"大"指的是超过
HDFS 块的大小,分片大小=总输入的大小/map任务数,最大的分片大小默认是由 Java long 类型表示的最大值。这样做的效果是:当它的值被设置成小于块大小时,将强制分片比块小。
小文件与CombineFilelnputFormat
相对于大批量的小文件, Hadoop 更合适处理少量的大文件,一个原因是FilelnputFormat 生成的 InputSplit 是一个文件或该文件的一部分, 如果文件很小( "小"意味着比 HDFS 的块要小很多) ,并且文件数量很多,那么每次 map任 务只处理很少的输入数据, (一个文件) 就会有很多 map 任务,每次 map 操作都会造成额外的开销。
CombineFilelnputFormat 可以缓解这个问题,它是针对小文件而设计的。 FilelnputFormat 为每个文件产生 1个分片,而 CombineFilelnputFormat 把多个文件打包到一个分片中以便每个 mapper 可以处理更多的数据。关键是,决定哪些块放入同一个分片时,CombineFilelnputFormat 会考虑到节点和机架的因素,所以在典型 MapReduce 作业中处理输入的速度井不会下降。
应该尽量避免许多小文件的情况,因为 MapReduce 处理数据的最佳速度最好与数据在集群中的传输速度相同,而处理小文件将增加运行作业而必需的寻址次数。还有,在 HDFS 集群中存储大量的小文件会浪费 namenode 的内存。一个可以减少大量小文件的方陆是使用 SequenceFile 将这些小文件合并成一个或多个大文件:可以将文件名作为键(如果不需要键,可以用 NullWritable等常量代替),文件的内容作为值。
避免切分
有些应用程序可能不希望文件被切分,而是用一个
mapper 完整处理每一个输入文件,有两种方法可以保证输入文件不被切分。第一种(最简单但不怎么漂亮的)方法就是
增加最小分片大小,将它设置成大于要处理的最大文件大小,第二种方法就是使用 FilelnputFormat 具体子类,井且重载 isSplitable() 方法把返回值设置为 false。
文本输入:
Hadoop
非常擅长处理非结构化文本数据。
TextlnputFormat 是默认的,InputFormat 。每条记录是一行输入。键是 LongWritable 类型,存储该行在整个文件中的字节偏移量。值是这行的内容,不包括任何行终止符(换行符和回车符)
,它是
Text
类型的。FilelnputFormat 定义的逻辑记录有时并不能很好地匹配 HDFS 的文件块。
例如,
TextlnputFormat 的逻辑记录是以行为单位的,那么很有可能某一行会跨文件块存放
通过
TextlnputFormat KeyValueTextI
utFormat
,每个
mapper 收到的输入行数不同。行数依赖于输入分片的大小和行的长度。如果希望
mapper 收到固定行 数的输入,需要使用
Li
nelnputFor
mat
作为
InputFormat。
二进制输入:
Hadoop MapReduce 不只是可以处理文本信息,它还可以处理二进制格式的数据。Hadoop 的顺序文件格式存储二进制的键/值对的序列。
6.2 输出格式
默认的输出格式是
TextOutputFor
mat ,它把每条记录写为文本行。它的键和值可以是任意类型,因为
TextOutputFor
mat
调用
toStri
ng()
方法把它们转换为字符
串。
二进制输出
SequenceFileOutputFo
mat 将它的输出写为一个顺序文件。如果输出需要作为后续
MapReduce 任务的输入,这便是一种好的输出格式,因为它的格式紧凑,很容易被压缩。
reduce
输入的键一定是有序的,但输出的键由
reduce 函数控制, MapReduce
框架中没有硬性规定
reduce
输出键必须有序。
MultipleOutputFormat 类可以将数据写到多个文件,这些文件的名称源于输出的键和值。