在 Hadoop MapReduce 中,Reduce 任务的数量(即 Reducer 个数) 是一个关键配置参数,它直接影响作业的并行度、负载均衡和性能。这个数量 不是自动推断的,而是由用户或框架根据配置策略决定的。
一、Reduce 任务数量的确定方式
✅ 1. 用户显式设置(最常用)
通过代码或命令行指定 Reducer 数量:
(1)在 Java 代码中设置:
Job job = Job.getInstance(conf, "MyJob");
job.setNumReduceTasks(5); // 设置为 5 个 Reduce 任务
(2)在命令行提交作业时设置:
hadoop jar myjob.jar -D mapreduce.job.reduces=5 input output
🔸 这是最推荐的方式:开发者根据数据规模、集群资源和业务需求主动控制并行度。
✅ 2. 默认值(未显式设置时)
- 如果 没有调用
setNumReduceTasks(),MapReduce 会使用默认值:public static final int DEFAULT_REDUCE_TASKS = 1; - 即:默认只有 1 个 Reduce 任务。
⚠️ 风险:
- 所有 Map 输出都由 单个 Reducer 处理,容易成为性能瓶颈;
- 无法利用集群并行能力,作业变慢;
- 可能导致 Reducer 节点内存溢出(OOM)。
❌ 3. 不会根据输入数据量自动调整
与 Map 任务不同(Map 数 ≈ InputSplit 数 ≈ 数据块数),Reduce 任务数与输入数据大小无关,完全由用户或配置决定。
📌 对比:
- Map 数:由输入数据分片(InputSplit)数量决定(自动);
- Reduce 数:必须手动设置(除非接受默认值 1)。
二、如何合理设置 Reduce 任务数量?
虽然不能自动推断,但有经验法则可参考:
📏 经验公式(Cloudera / 社区推荐):
Reducer 数 ≈ 集群总 Reduce Slot 数 × 0.9 ~ 1.0
其中:
- Reduce Slot 数 = 集群节点数 × 每节点 Reduce 任务槽位数
- 可通过 YARN 配置查看:
yarn.scheduler.maximum-allocation-mb和mapreduce.reduce.memory.mb等
📊 或按输出数据量估算:
每个 Reducer 处理 1~2 GB 的中间数据较合理
例如:
- Shuffle 总数据量 ≈ 100 GB
- 则 Reducer 数 ≈ 100 / 1.5 ≈ 67 个
💡 提示:可通过上一次作业的 Counters 查看
"Reduce shuffle bytes"获取中间数据量。
三、特殊场景:0 个 Reduce 任务
可以设置:
job.setNumReduceTasks(0);
此时:
- 没有 Reduce 阶段;
- Map 的输出直接写入 HDFS(作为最终结果);
- 适用于 只需过滤/转换、无需聚合 的场景(如日志清洗)。
📁 输出由
FileOutputFormat控制,文件名为part-m-00000等。
四、相关配置参数
| 参数 | 默认值 | 说明 |
|---|---|---|
mapreduce.job.reduces | 1 | 全局设置 Reduce 任务数 |
mapreduce.reduce.memory.mb | 1024 | 每个 Reducer 的内存 |
mapreduce.reduce.cpu.vcores | 1 | 每个 Reducer 的 CPU 核数 |
五、常见误区
| 误区 | 正确理解 |
|---|---|
| “Reduce 数越多越好” | 过多会导致小文件问题、调度开销增大、资源浪费 |
| “Hadoop 会自动优化 Reducer 数” | 不会!必须手动设置 |
| “Reduce 数 = Map 数” | 无直接关系,两者独立配置 |
六、总结
| 问题 | 答案 |
|---|---|
| 谁决定 Reduce 任务数量? | 用户(通过代码或配置) |
| 默认是多少? | 1 个 |
| 能否自动根据数据量调整? | ❌ 不能 |
| 最佳实践? | 根据集群资源和中间数据量合理设置(通常几十到几百) |
| 什么时候设为 0? | 不需要 Reduce 阶段时(纯 Map 作业) |
✅ 建议:生产环境中永远不要依赖默认值 1,应根据实际负载测试确定最优 Reducer 数量。
7万+

被折叠的 条评论
为什么被折叠?



