目录
MapReduce跑的慢的原因
MapReduce程序效率的瓶颈在于两点:
1)计算机性能
CPU、内存、磁盘、网络
2)I/O操作优化
(1)数据倾斜
(2)Map运行时间太长,导致Reduce等待过久
(3)小文件过多
MapReduce常用调优参数
1. MapTask相关参数
- mapreduce.task.io.sort.mb: 设置Map端排序的内存大小,默认为100MB。增加此值可以减少溢写磁盘的次数,但需要根据集群内存情况调整。
- mapreduce.map.sort.spill.percent: Map端溢写阈值,默认为0.80。当Map端缓存区达到该比例时会触发溢写操作。
- mapreduce.map.memory.mb: 每个MapTask分配的最大内存,默认根据集群配置。
- mapreduce.map.java.opts: 设置MapTask JVM的启动参数,可以用来调整JVM的堆内存大小等。
2. ReduceTask相关参数
- mapreduce.reduce.memory.mb: 每个ReduceTask分配的最大内存,默认根据集群配置。
- mapreduce.reduce.java.opts: 设置ReduceTask JVM的启动参数,同样可以用来调整JVM的堆内存大小等。
- mapreduce.job.reduces: 设置ReduceTask的数量,合理设置可以平衡负载和任务执行效率。
- mapreduce.reduce.shuffle.parallelcopies: 控制Reduce端同时进行的合并操作数量。
3. 总体调优参数
- mapreduce.job.reduce.slowstart.completedmaps: 控制ReduceTask开始执行前等待MapTask完成的比例,默认为0.05,即5%。
- yarn.nodemanager.vmem-pmem-ratio: 虚拟内存与物理内存的比例,用于计算每个容器所需的虚拟内存大小。
- yarn.scheduler.maximum-allocation-mb: YARN调度器为任务分配的最大内存。
- yarn.scheduler.minimum-allocation-mb: YARN调度器为任务分配的最小内存。
4. 其他重要参数
- mapreduce.input.fileinputformat.split.minsize: 输入文件的最小切片大小。
- mapreduce.input.fileinputformat.split.maxsize: 输入文件的最大切片大小。
- mapreduce.job.cache.files: 添加到Job的缓存文件列表。
- mapreduce.job.cache.archives: 添加到Job的缓存归档文件列表。
调优策略
- 资源分配: 根据集群资源和作业需求合理分配MapTask和ReduceTask的资源。
- 并发度: 适当增加并发度可以加快作业执行速度。
- 数据分区: 合理的数据分区可以减少网络传输量。
- 压缩: 对中间结果进行压缩可以减少I/O开销。
MapReduce数据倾斜问题
1)数据倾斜现象
数据频率倾斜——某一个区域的数据量要远远大于其他区域。
数据大小倾斜——部分记录的大小远远大于平均值。
2)减少数据倾斜的方法
1. 数据预处理
- 数据过滤: 在Map阶段通过过滤掉一些不必要的数据,减少处理的数据量。
- 数据采样: 对输入数据进行采样分析,了解数据分布特性,从而更合理地进行后续处理。
2. 自定义Partitioner
- 重新设计Partitioner: 通过自定义Partitioner算法,使数据更均匀地分配给各个Reduce任务。
- 使用哈希函数: 使用哈希函数将key映射到特定的Reduce任务上,避免所有相同key的数据都发送到同一个Reduce任务。
3. 调整Reduce任务数
- 增加Reduce任务数: 通过增加Reduce任务的数量来分散数据处理的压力。
- 动态调整: 根据数据分布的实际情况动态调整Reduce任务的数量。
4. 小文件问题处理
- CombineTextInputFormat: 使用CombineTextInputFormat作为InputFormat,它可以合并小文件,减少Map任务的数量。
- Combiner: 在Map阶段使用Combiner对数据进行局部聚合,减少中间数据量。
5. 二次排序
- 优化Map输出: 在Map阶段优化输出格式,例如使用缓冲区来收集和排序数据,减少数据倾斜。
- Buffering: 在Map阶段设置合理的buffer size来控制数据溢写的时间点。
6. 使用桶表
- 构建桶表: 如果数据分布不均是由于key的分布不均引起的,可以考虑先创建一个“桶表”,将数据按照某种规则预先分配到不同的“桶”中。
7. 使用随机前缀
- 添加随机前缀: 对于一些特别热门的key,可以在key前面加上随机前缀,这样即使原本相同的key也会被分配到不同的Reduce任务上。
8. 参数调优
- 调整MapReduce的参数: 如
mapreduce.task.io.sort.mb
(Map端排序内存大小),mapreduce.job.reduces
(Reduce任务数量)等,以适应不同数据集的特点。
实施步骤
- 分析数据分布: 使用工具或脚本分析输入数据的分布情况,找出可能导致倾斜的关键因素。
- 评估方案: 根据分析结果评估哪种方案更适合当前的情况。
- 实施和测试: 实施所选方案,并在测试环境中验证其效果。
- 监控和调整: 在生产环境中持续监控MapReduce作业的性能,并根据实际情况进行调整。