性能调优
本章将介绍 Hadoop 集群的性能调优方法,包括硬件优化、配置优化、JVM 调优等方面。
调优概述
调优目标
Hadoop 性能调优的主要目标:
- 提高吞吐量:单位时间内处理更多数据
- 降低延迟:减少作业执行时间
- 提高资源利用率:充分利用集群资源
- 保证稳定性:避免 OOM、超时等问题
调优思路
硬件层面优化
硬件选型建议
| 组件 | 推荐配置 | 说明 |
|---|---|---|
| CPU | 16-24 核 | 多核提高并行度 |
| 内存 | 64-128GB | NameNode 需要大内存 |
| 磁盘 | 多块独立磁盘 | 提高并行 IO 能力 |
| 网络 | 万兆网卡 | 减少网络瓶颈 |
磁盘配置
DataNode 磁盘配置:
<!-- 多目录配置,提高并行度 -->
<property>
<name>dfs.datanode.data.dir</name>
<value>/data1,/data2,/data3,/data4</value>
</property>
磁盘选型建议:
- 使用独立磁盘控制器
- 避免使用 RAID(HDFS 已有副本机制)
- SSD 用于热数据,HDD 用于冷数据
网络优化
机架感知配置:
合理配置机架感知,减少跨机架网络传输。
网络参数优化:
# 增大 TCP 缓冲区
sysctl -w net.core.rmem_max=134217728
sysctl -w net.core.wmem_max=134217728
sysctl -w net.ipv4.tcp_rmem=4096 87380 134217728
sysctl -w net.ipv4.tcp_wmem=4096 65536 134217728
# 开启 TCP 窗口缩放
sysctl -w net.ipv4.tcp_window_scaling=1
HDFS 调优
NameNode 调优
内存配置
NameNode 内存需求与文件数量相关:
- 每个文件约占用 150 字节内存
- 100 万文件约需要 150MB 内存
- 建议预留 50% 的内存余量
<!-- NameNode JVM 堆内存 -->
<property>
<name>dfs.namenode.handler.count</name>
<value>100</value>
</property>
启动脚本配置:
# 在 hadoop-env.sh 中设置
export HADOOP_HEAPSIZE_MAX=32768 # 32GB
export HADOOP_NAMENODE_OPTS="-Xmx32g -Xms32g"
处理器线程数
<!-- NameNode 处理 RPC 请求的线程数 -->
<property>
<name>dfs.namenode.handler.count</name>
<value>100</value>
</property>
<!-- 服务 RPC 线程数 -->
<property>
<name>dfs.namenode.service.handler.count</name>
<value>100</value>
</property>
DataNode 调优
处理器线程数
<!-- DataNode 处理请求的线程数 -->
<property>
<name>dfs.datanode.handler.count</name>
<value>10</value>
</property>
<!-- 数据传输线程数 -->
<property>
<name>dfs.datanode.max.transfer.threads</name>
<value>4096</value>
</property>
数据块配置
<!-- 数据块大小 -->
<property>
<name>dfs.blocksize</name>
<value>134217728</value>
</property>
<!-- 副本数 -->
<property>
<name>dfs.replication</name>
<value>3</value>
</property>
客户端调优
<!-- 客户端缓存大小 -->
<property>
<name>io.file.buffer.size</name>
<value>131072</value>
</property>
<!-- 读取重试次数 -->
<property>
<name>ipc.client.connect.max.retries</name>
<value>50</value>
</property>
MapReduce 调优
Map 任务调优
内存配置
<!-- Map 任务内存 -->
<property>
<name>mapreduce.map.memory.mb</name>
<value>2048</value>
</property>
<!-- Map JVM 参数 -->
<property>
<name>mapreduce.map.java.opts</name>
<value>-Xmx1638m -XX:+UseG1GC</value>
</property>
环形缓冲区
<!-- 缓冲区大小 -->
<property>
<name>mapreduce.task.io.sort.mb</name>
<value>256</value>
</property>
<!-- 溢写阈值 -->
<property>
<name>mapreduce.map.sort.spill.percent</name>
<value>0.80</value>
</property>
<!-- 合并因子 -->
<property>
<name>mapreduce.task.io.sort.factor</name>
<value>20</value>
</property>
Reduce 任务调优
内存配置
<!-- Reduce 任务内存 -->
<property>
<name>mapreduce.reduce.memory.mb</name>
<value>4096</value>
</property>
<!-- Reduce JVM 参数 -->
<property>
<name>mapreduce.reduce.java.opts</name>
<value>-Xmx3276m -XX:+UseG1GC</value>
</property>
Shuffle 优化
<!-- 拉取并行数 -->
<property>
<name>mapreduce.reduce.shuffle.parallelcopies</name>
<value>10</value>
</property>
<!-- 内存缓冲比例 -->
<property>
<name>mapreduce.reduce.shuffle.input.buffer.percent</name>
<value>0.70</value>
</property>
<!-- Reduce 计算缓冲 -->
<property>
<name>mapreduce.reduce.input.buffer.percent</name>
<value>0.30</value>
</property>
压缩优化
<!-- Map 输出压缩 -->
<property>
<name>mapreduce.map.output.compress</name>
<value>true</value>
</property>
<property>
<name>mapreduce.map.output.compress.codec</name>
<value>org.apache.hadoop.io.compress.SnappyCodec</value>
</property>
<!-- Reduce 输出压缩 -->
<property>
<name>mapreduce.output.fileoutputformat.compress</name>
<value>true</value>
</property>
<property>
<name>mapreduce.output.fileoutputformat.compress.codec</name>
<value>org.apache.hadoop.io.compress.GzipCodec</value>
</property>
任务数量优化
<!-- Map 任务数量(通过分片大小控制) -->
<property>
<name>mapreduce.input.fileinputformat.split.minsize</name>
<value>134217728</value>
</property>
<!-- Reduce 任务数量 -->
<property>
<name>mapreduce.job.reduces</name>
<value>10</value>
</property>
YARN 调优
ResourceManager 调优
<!-- RM 内存 -->
<property>
<name>yarn.resourcemanager.scheduler.client.thread-count</name>
<value>50</value>
</property>
<!-- 心跳间隔 -->
<property>
<name>yarn.resourcemanager.nodemanagers.heartbeat-interval-ms</name>
<value>1000</value>
</property>
NodeManager 调优
<!-- 节点资源 -->
<property>
<name>yarn.nodemanager.resource.memory-mb</name>
<value>65536</value>
</property>
<property>
<name>yarn.nodemanager.resource.cpu-vcores</name>
<value>16</value>
</property>
<!-- 资源分配 -->
<property>
<name>yarn.scheduler.minimum-allocation-mb</name>
<value>1024</value>
</property>
<property>
<name>yarn.scheduler.maximum-allocation-mb</name>
<value>32768</value>
</property>
<!-- AM 比例 -->
<property>
<name>yarn.scheduler.capacity.maximum-am-resource-percent</name>
<value>0.2</value>
</property>
JVM 调优
垃圾收集器选择
G1 GC(推荐):
# 适用于大内存场景
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
-XX:InitiatingHeapOccupancyPercent=45
CMS GC:
# 适用于低延迟场景
-XX:+UseConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction=70
-XX:+UseCMSInitiatingOccupancyOnly
JVM 参数配置
NameNode JVM:
export HADOOP_NAMENODE_OPTS="-Xmx32g -Xms32g \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=200 \
-XX:+PrintGCDetails \
-XX:+PrintGCDateStamps \
-Xloggc:/var/log/hadoop/namenode-gc.log"
DataNode JVM:
export HADOOP_DATANODE_OPTS="-Xmx4g -Xms4g \
-XX:+UseG1GC \
-XX:MaxGCPauseMillis=200"
Map/Reduce JVM:
<property>
<name>mapreduce.map.java.opts</name>
<value>-Xmx1638m -XX:+UseG1GC -XX:MaxGCPauseMillis=100</value>
</property>
<property>
<name>mapreduce.reduce.java.opts</name>
<value>-Xmx3276m -XX:+UseG1GC -XX:MaxGCPauseMillis=100</value>
</property>
常见问题排查
性能瓶颈定位
使用系统工具:
# CPU 使用情况
top -H -p <pid>
# 内存使用情况
jmap -heap <pid>
# 磁盘 IO
iostat -x 1
# 网络流量
iftop
使用 Hadoop 工具:
# 查看 HDFS 状态
hdfs dfsadmin -report
# 查看作业计数器
yarn application -status <app_id>
# 查看任务日志
yarn logs -applicationId <app_id>
数据倾斜
现象: 大部分 Reduce 很快完成,个别 Reduce 执行很慢。
解决方案:
- 分析数据分布
- 自定义 Partitioner
- 增加 Reduce 数量
- 使用 Combiner
小文件问题
现象: NameNode 内存占用高,Map 任务数量多。
解决方案:
- 使用 CombineFileInputFormat
- 定期合并小文件
- 使用 SequenceFile 存储
- 开启 HDFS 档案
# 合并小文件
hadoop archive -archiveName files.har -p /input /output
内存溢出
现象: 任务失败,日志显示 OOM。
解决方案:
- 增加任务内存配置
- 优化代码减少内存占用
- 调整 JVM 参数
- 使用外部排序
监控与告警
关键监控指标
| 组件 | 指标 | 说明 |
|---|---|---|
| NameNode | 内存使用率 | 元数据占用内存 |
| NameNode | 文件数量 | 影响内存需求 |
| DataNode | 磁盘使用率 | 存储容量 |
| ResourceManager | 集群资源使用率 | 资源利用率 |
| NodeManager | 节点资源使用率 | 单节点负载 |
Web UI 监控
- NameNode:http://namenode:9870
- ResourceManager:http://resourcemanager:8088
- 历史服务器:http://historyserver:19888
小结
本章介绍了 Hadoop 性能调优的方法:
-
硬件优化:选择合适的硬件配置,优化磁盘和网络。
-
HDFS 调优:NameNode 内存、DataNode 线程、客户端缓存等。
-
MapReduce 调优:内存配置、Shuffle 优化、压缩配置等。
-
YARN 调优:资源配置、调度器优化等。
-
JVM 调优:垃圾收集器选择、JVM 参数配置。
性能调优是一个持续的过程,需要根据实际负载不断调整和优化。