跳到主要内容

性能调优

本章将介绍 Hadoop 集群的性能调优方法,包括硬件优化、配置优化、JVM 调优等方面。

调优概述

调优目标

Hadoop 性能调优的主要目标:

  1. 提高吞吐量:单位时间内处理更多数据
  2. 降低延迟:减少作业执行时间
  3. 提高资源利用率:充分利用集群资源
  4. 保证稳定性:避免 OOM、超时等问题

调优思路

硬件层面优化

硬件选型建议

组件推荐配置说明
CPU16-24 核多核提高并行度
内存64-128GBNameNode 需要大内存
磁盘多块独立磁盘提高并行 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 执行很慢。

解决方案:

  1. 分析数据分布
  2. 自定义 Partitioner
  3. 增加 Reduce 数量
  4. 使用 Combiner

小文件问题

现象: NameNode 内存占用高,Map 任务数量多。

解决方案:

  1. 使用 CombineFileInputFormat
  2. 定期合并小文件
  3. 使用 SequenceFile 存储
  4. 开启 HDFS 档案
# 合并小文件
hadoop archive -archiveName files.har -p /input /output

内存溢出

现象: 任务失败,日志显示 OOM。

解决方案:

  1. 增加任务内存配置
  2. 优化代码减少内存占用
  3. 调整 JVM 参数
  4. 使用外部排序

监控与告警

关键监控指标

组件指标说明
NameNode内存使用率元数据占用内存
NameNode文件数量影响内存需求
DataNode磁盘使用率存储容量
ResourceManager集群资源使用率资源利用率
NodeManager节点资源使用率单节点负载

Web UI 监控

小结

本章介绍了 Hadoop 性能调优的方法:

  1. 硬件优化:选择合适的硬件配置,优化磁盘和网络。

  2. HDFS 调优:NameNode 内存、DataNode 线程、客户端缓存等。

  3. MapReduce 调优:内存配置、Shuffle 优化、压缩配置等。

  4. YARN 调优:资源配置、调度器优化等。

  5. JVM 调优:垃圾收集器选择、JVM 参数配置。

性能调优是一个持续的过程,需要根据实际负载不断调整和优化。