1. MapTask工作机制
以上内容我们之前文章或多或少介绍过,就已网络上比较流行的该图进行理解学习吧
MapTask分为五大阶段
- Read阶段
- Map阶段
- Collect阶段
- 溢写阶段
- Merge阶段
2. ReduceTask工作机制
ReduceTask分为三大阶段
- Copy阶段
- Sort阶段
- Reduce阶段
2.1 ReduceTask并行度决定机制
MapTask并行度由切片个数决定,切片个数由输入文件和切片规则决定,ReduceTask与MapTask的并发数决定不同,可以直接设置
job.setNumReduceTasks(4);
2.2 ReduceTask注意事项
- ReduceTask=0,表示没有Reduce阶段,输出文件数与Map阶段输出个数一致
- ReduceTask默认值1,所以输出文件是一个
- 如果数据分布不均匀,就有可能Reduce阶段产生数据倾斜
- ReduceTask数量并不是任意设置,要考虑业务需求,当需要计算全局汇总结果,就只能有1个ReduceTask
- 具体多少个ReduceTask,需要根据集群性能而定
- 如果分区数不是1,但是ReduceTask为1,不会执行分区过程,在MapTask源码中,分区前提是先判断ReduceNum个数是否大于1,不大于1肯定不执行分区
3. Shuffle机制
Map方法之后,Reduce方法之前的数据处理过程称为Shuffle
4. MapReduce数据压缩
4.1 压缩概述
压缩优缺点:减少磁盘IO时间、节省磁盘空间;增加CPU开销
压缩原则:CPU密集型Job,少用压缩;IO密集型Job,多用压缩
4.2 压缩算法比较
压缩格式 | Hadoop自带 | 算法 | 扩展名 | 可切片 | 程序是否需修改 | 压缩速度MB/S | 解压速度MB/S |
---|---|---|---|---|---|---|---|
DEFLATE | 是 | DEFLATE | .deflate | 否 | 否 | ||
Gzip | 是 | DEFLATE | .gz | 否 | 否 | 17.5 | 58 |
Bzip2 | 是 | bzip2 | .bz2 | 是 | 否 | 2.4 | 9.5 |
LZO | 否,需安装 | LZO | .lzo | 是 | 需要建索引并指定输入格式 | 49.3 | 74.6 |
Snappy | 是 | Snappy | .snappy | 否 | 否 | 250 | 500 |
4.3 压缩算法选择
压缩方式选择时重点考虑:解压缩速度、压缩率、压缩后是否支持切片
Mapper输入端压缩:无需显示指定编解码方式。Hadoop自动检查文件扩展名,如果匹配,就会用恰当的方式对文件进行压缩和解压。数据量小于块大小,重点考虑压缩比较快的LZO与Snappy;如果数据量非常大,重点考虑支持切片的Bzip2和LZO
Mapper输出端压缩:为了减少MapTask和ReduceTask之间的网络IO,重点考虑解压缩比较快的LZO与Snappy
Reducer输出端压缩:如果数据永久保存,考虑压缩率比较高的Bzip2和Gzip
4.4 压缩算法实践
我们执行hadoop checknative
查看目前支持的算法
public class WordCountCompressDriver {
public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {
Configuration conf = new Configuration();
// 开启map端输出压缩
conf.setBoolean("mapreduce.map.output.compress", true);
// 设置map端输出压缩格式
conf.setClass("mapreduce.map.output.compress.codec", BZip2Codec.class, CompressionCodec.class);
Job job = Job.getInstance(conf, "word count");
job.setJarByClass(WordCountCompressDriver.class);
job.setMapperClass(WordCountMapper.class);
job.setCombinerClass(WordCountReduce.class);
job.setReducerClass(WordCountReduce.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
// 开始Reduce端输出压缩
FileOutputFormat.setCompressOutput(job, true);
//FileOutputFormat.setOutputCompressorClass(job, BZip2Codec.class);
// 设置压缩编码
FileOutputFormat.setOutputCompressorClass(job, GzipCodec.class);
FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}
欢迎关注公众号算法小生与我沟通交流