一个任务的开始阶段是由InputFormat来决定的!
1.在MapReduce框架中,InputFormat扮演的角色:
– 将输入数据切分成逻辑的分片(Split),一个分片将被分配给一个单独的Mapper
– 提供RecordReader的对象,该对象会从分片中读出<Key-Value>对供Mapper
处理
1.1InputFormat对Mapper的影响:
– 决定了Mapper的数量
– 决定了Mapper的map函数接收的Key和Value
1.2InputFormat:
InputFormat源码解释:
getSplits负责将输入数据进行划分,生成一组分片
createRecordReader返回的对象,负责从分片中读取<Key-Value>对
1.3InputSplit源码解释:
InputSplit是一个抽象类,分片的类都继承自它
方法getLength()用于获取分片的大小
方法getLocations()用于获取存储分片的位置列表
2.MapReduce调用RecordReader,Mapper类的run函数
Mapper通过context来获取Key-Value对,而context的nextKeyValue、
getCurrentKey、getCurrentKey方法,就是调用InputFormat返回的RecordReader对象
3.InputFormat:类层次结构
3.1FileInputFormat:
FileInputFormat是InputFormat的子类,所有使用文件为数据源的输入格式类都继承
自它
---实现了getSplits方法
---返回的分片类型是FileSplit,是InputSplit的子类,里面加入了描述文件路径,分片开始位置
的信息
---没有实现createRecordReader方法,是一个抽象类
FileInputFormat:生成分片
默认情况下为文件在HDFS上的每一个block都生成一个分片
---可通过作业的配置参数mapred.min.split.size和mapred.max.split.size来设置分片大
小的最小值和最大值,设置这两个参数后,可能会对文件连续的block生成一个分片,
使分片大小在指定的范围内。
---一个分片包含的block只来自一个文件
4. MapReduce默认的输入格式是:TextInputformat
TextInputFormat
TextInputFormat 是默认的输入格式
? 是FileInputFormat的子类,继承了它的getSplit方法
? createRecordReader返回的是lineRecordReader的对象
– 每行数据生成一条<Key, Value>记录
– Key:每个数据的记录在数据分片中字节偏移量,类型是LongWritable
– Value:每行的内容,类型是Text
如果输入文件有上万个,那么就需要调用至少上万个Mapper!
4.1自定义输入格式,来解决小文件问题:
CombineFileInputFormat
CombineFileInputFormat是针对小文件设计的输入格式
? 继承了类FileInputFormat
? 重写了getSplit方法
– 返回的分片类型是CombineFileSplit,是InputSplit的子类,可包含多个文件的路径
? 是一个抽象类,编写具体类需要实现createRecordReader方法
– 建议返回值的类型是CombineFileRecordReader,它用于处理类型为CombineFileSplit的分
片
– CombineFileRecordReader的构造函数中,还需指定一个RecordReader,用于处理分片内
的单个文件
CombineFileInputFormat:生成分片
输出的分片中可包含多个不同文件的block
? 文件切分原理:http://blog.sina.com.cn/s/blog_5673f78b0101etz4.html
自定义输入格式MyInputFormat:
确保文件不被分割,每个文件都只分配到一个分片
? 一个分片可包含多个文件
? 输出的每条<Key, Value>对应一个完整的文本文件
– Key: 文件所属的类别名, 类型是Text
– Value: 文件的文本内容, 类型是Text