[ hadoop ] 集群性能调优全面总结_bone_ds的博客-CSDN博客_hadoop集群优化
引子
文章涵盖了hadoop框架的三个组成架构各自的优化方法,涉及存储,计算,故障排除等多个方面的具体调优内容,先后解决HDFS,MapReduce,Yarn的常见问题,最终结合小文件问题给出了Hadoop综合调优.
1 HDFS调优
1.1 核心参数
1.1.1 NameNode内存
Hadoop2.x系列,NN内存默认2000M,根据服务器(以4G为例)的3/4来配:
hadoop-env.sh文件中配置:HADOOP_NAMENODE_OPTS=-Xmx3072m
Hadoop3.x系列,hadoop-env.sh文件中说明了内存自动分配.
通过命令 jmap -heap < jps查看到的进程的PID >可知NameNode和DataNode占用内存都是自动分配的,且相等。不是很合理。
手动配置:hadoop-env.sh
export HDFS_NAMENODE_OPTS="-Dhadoop.security.logger=INFO,RFAS -Xmx1024m"
export HDFS_DATANODE_OPTS="-Dhadoop.security.logger=ERROR,RFAS -Xmx1024m"
1.1.2 NameNode心跳并发
NameNode有一个工作线程池,用来处理不同DataNode的并发心跳以及客户端并发的元数据操作。
线程数dfs.namenode.handler.count默认是10,按企业经验hdfs-site.xml中该值设为
1.1.3 开启回收站
将删除的文件在不超时的情况下恢复,防止误删
修改core-site.xml中回收时间fs.trash.interval值为60,以及检查间隔fs.trash.checkpoint.interval值为小于回收时间
查看回收站:HDFS中路径:/user/用户名/.Trash/…
web端删除不经过回收站,或者通过程序删除只有使用moveToTrash()才走回收站,此外shell操作命令使用hadoop fs -rm才走回收站
恢复数据的话将回收站路径下文件移动即可
1.2 集群压测
考虑到Java后台拉取的数据用多久能上传到集群,以及从HDFS上拉取数据的时间,因此对集群压测以测出HDFS的读写性能
说明:HDFS的读写性能主要受限于网络和磁盘.
1.2.1 写性能测试
前提:设置集群网速为100Mbps单位是bit;换算后为12.5M/s
测试步骤:
1. yarn-site.xml中设置关闭虚拟内存检测(避免centos和jdk的不兼容),分发
2.向HDFS写10个128M的文件(文件数>两个节点总核数就行,保证每个节点都有任务)
命令:hadoop jar /opt/module/hadoop-3.1.3/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-3.1.3-tests.jar TestDFSIO -write -nrFiles 10 -fileSize 128MB
结果分析:
- 忽略客户端所在节点的本地副本,参与测试的一共20个文件写入集群
- 压测后的速度(单个文件的写速度):1.61
- 实测速度:1.61*20=32M/s
- 三台服务器带宽:12.5*3略大于实测速度
结论:说明所有网络资源已用满,因此写速度主要受限于网络传输速度
1.2.2 读性能测试
1. 将上面10个文件读取:
hadoop jar /opt/module/hadoop-3.1.3/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-3.1.3-tests.jar TestDFSIO -read -nrFiles 10 -fileSize 128MB
2. 测试完毕,收尾,删除测试数据
hadoop jar /opt/module/hadoop-3.1.3/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-3.1.3-tests.jar TestDFSIO -clean
观察到读取结果远大于网络带宽
结论:
测试节点存在文件副本,就近读取,读的本地磁盘,没经过网络,读速度不受网络限制,只受磁盘读写速度限制.
1.3 多目录
1.3.1 NameNode多目录配置
NN本地目录配置为多个,每个目录存放内容相同
说明:备份了nn,提高了可靠性,但不是高可用,nn所在节点挂掉集群仍无法工作
步骤:
- hdfs-site.xml中添加内容,将dfs.namenode.name.dir修改为两个目录
- 停止集群,删除所有节点的date和logs中数据
- 格式化nn后启动集群
1.3.2 DataNode多目录配置
DN可以配置成多目录,不同于nn的备份,dn多目录存放不同数据,解决磁盘空间不足问题
步骤:
- hdfs-site.xml中添加内容,将dfs.datanode.data.dir修改为两个目录
- 将该配置文件适量分发,因每个服务器配置可能不同,分发请慎重
1.3.3 磁盘间数据均衡
增加一块硬盘。刚加载的硬盘没有数据时,可以执行磁盘数据均衡命令。
说明:这是Hadoop3.x新特性,单节点内部磁盘均衡
步骤:
- 生成均衡计划: hdfs diskbalancer -plan hadoop103
- 执行均衡计划: hdfs diskbalancer -execute hadoop103.plan.json
- 查看当前均衡任务的执行情况: hdfs diskbalancer -query hadoop103
- 取消均衡任务: hdfs diskbalancer -cancel hadoop103.plan.json
1.4 集群扩容及缩容
1.4.1 添加白名单
在白名单的主机IP地址才可以用来存储数据。可以尽量防止黑客恶意访问攻击。
步骤:
- 在hadoop软件包下的etc/hadoop目录下创建whitelist和blacklist文件
- whitelist文件中加入集群节点的ip或主机名(映射)
- hdfs-site.xml中增加dfs.hosts配置参数为whitelist路径并分发
- 第一次创白名单得重启集群,否则只需刷新nn节点(hdfs dfsadmin -refreshNodes)
1.4.2 服役新服务器
动态增加服务器,不重启集群即可实现服役新服务器,主要解决数据节点容量不足.
步骤:
- 环境准备:修改新主机的ip,主机名;将软件包目录和环境变量脚本拷贝过来;清空,data和log目录下的数据;配置和其他节点的无密登录
- 服役新节点:启动该节点的datanode和nodemanager的后台进程
- 白名单中增加待加入的节点并分发
- 刷新nn
1.4.3 服务器间数据均衡
如果常在某个节点提交任务,由于数据本地性原则,该节点数据量过多,造成数据节点间量的 差距,或者,新服役的服务器数据量比较少,需要执行集群均衡命令。
- 开启数据均衡命令:start-balancer.sh -threshold 10(10 代表的是集群中各个节点的磁盘空间利用率相差不超过10%,可根据实际情况进行调整)
- 停止数据均衡命令:stop-balancer.sh
1.4.4 黑名单退役服务器
步骤:
- 在hadoop软件包目录的etc/hadoop目录下编辑blacklist文件:添加要退役的节点
- 在hdfs-site.xml配置文件中增加dfs.hosts.exclude配置参数,分发
- 同白名单一样,第一次创黑名单需重启集群,否则刷新nn节点
说明:
- 节点退役时,web界面可以看到,退役节点的状态为decommission in progress(退役中),说明数据节点正在复制块到其他节点
- 此操作是保证副本数满足要求, 如果副本数是3,服役的节点小于等于3,是不能退役成功的,需要修改副本数后才能退役
- 如果节点间数据不均衡,可以用命令再平衡
1.5 存储优化
1.5.1 纠删码
Hadoop3.x引入了纠删码,采用计算的方式,可以节省约50%左右的存储空间。
确切的说:给hdfs的一个路径设置单副本存储策略
纠删码策略:
- RS-3-2-1024k
- RS-10-4-1024k
- RS-6-3-1024k
- RS-LEGACY-6-3-1024k
- XOR-2-1-1024k
说明(以第一种为例):
使用RS编码,每3个数据单元,生成2个校验单元,共5个单元,也就是说:这5个单元中,只要有任意的3个单元存在(不管是数据单元还是校验单元,只要总数=3),就可以得到原始数据。每个单元的大小1024k=1024*1024=1048576。
步骤:
- 开启对该策略的支持:hdfs ec -enablePolicy -policy < 策略 >
- hdfs上对某个路径的目录设置该策略:hdfs ec -setPolicy -path < 目录path > -policy < 策略 >
- 以该策略rs-3-2为例,上传的文件需大于等于3个单元才看出效果
1.5.2 异构存储
异构存储,又叫冷热数据分离,它不同于纠删码的单副本,它是给hdfs的一个路径设置多副本存储策略,手段:不同的数据,存储在不同类型的硬盘中,达到最佳性能
存储类型:
- RAM_DISK:内存镜像文件系统(内存)
- SSD:SSD固态硬盘(固态)
- DISK:普通磁盘,HDFS默认的存储类型(机械)
- ARCHIVE:归档
policy存储策略(上–>下:快–>慢):
shell操作命令:
- 查看存储策略:hdfs storagepolicies -listPolicies
- 设置指定的存储策略:hdfs storagepolicies -setStoragePolicy -path xxx -policy xxx
- 获取指定路径的存储策略:hdfs storagepolicies -getStoragePolicy -path xxx
- 取消存储策略:hdfs storagepolicies -unsetStoragePolicy -path xxx
- 查看文件块的分布:bin/hdfs fsck xxx -files -blocks -locations
- 查看集群节点:hadoop dfsadmin -report
具体实施步骤:
- 在需修改的节点修改hdfs-site.xml配置文件的参数:
统一副本数:dfs.replication
开启异构存储:dfs.storage.policy.enabled
修改该节点磁盘存储类型:dfs.datanode.data.dir
- 格式化nn,重启集群
- 未设置存储策略,所有文件块都存储在DISK下。所以,默认存储策略为HOT
- 修改存储策略,给数据升温/降温:set命令(可以看到文件块依然放在原处)
- hdfs mover xxx:让HDFS按照存储策略自行移动文件块,可以看到副本移动到策略里指定的类型的磁盘
补充:
关于LAZY_PERSIST策略的说明:
文件就不会按该策略如期出现在指定类型的磁盘,即一个副本存储在RAM_DISK,其他副本存储在DISK中,因为:
- dfs.datanode.max.locked.memory该参数未配置默认是0,即不允许放在内存中
- 虽然可调,但默认上限为64kb
- 上限就是max locked memory,虽然它也可调,但是易出错,不推荐,所以别使用该策略最好
1.6 故障排除
1.6.1 NameNode故障
前置工作:
- 模拟nn进程挂了,存储的数据也丢了,如何恢复
- 杀死进程(kill -9 PID),删除nn目录下的数据(/opt/module/hadoop-3.1.3/data/tmp/dfs/name)
问题解决:
- (在nn节点的dfs目录下操作)拷贝2NN中的数据到nn存储数据目录:scp -r 用户@主机名:/opt/module/hadoop-3.1.3/data/dfs/namesecondary/* ./name/
- 重启nn后台进程
说明:
前面HDFS架构中可以了解到: nn比2nn目录下多了一个正在追加写的Edits文件,里面写了集群最新的操作内容,所以这种故障的排除有个前提,就是近期的追加写文件里没有操作,才算完全恢复,因此该方式不算高可用(后期使用HA解决)
1.6.2 集群安全模式&磁盘修复
1.安全模式:文件系统只接受读数据请求,而不接受删除、修改等变更请求
2.进入安全模式场景:
1)nn在加载镜像文件和编辑日志期间处于安全模式;
2)NameNode再接收DataNode注册时,处于安全模式
3.退出安全模式条件(以下需全部满足):
1)可用数据节点>0
2)最多丢失一块block的所有副本
3)满足前两个条件并稳定30s
4.相关命令
命令 | 功能 |
hdfs dfsadmin -safemode get | 查看安全模式状态 |
hdfs dfsadmin -safemode enter | 进入安全模式状态 |
hdfs dfsadmin -safemode leave | 离开安全模式状态 |
hdfs dfsadmin -safemode wait | 等待安全模式状态 |
案例1:启动集群进入安全模式
启动集群后立即(30s以内)来到集群web界面删除数据,提示集群处于安全模式
案例2:磁盘修复
删除两个块的所有副本,重启集群–>web界面提示块数量对不上警告–>输入命令离开安全模式–>依然警告–>不管则每次安全模式开启时都会警告–>解决办法:将警告信息中的已经丢失的文件块对应的元数据删除,或者联系磁盘厂家修复–>集群正常
案例3:模拟等待安全模式
先进入安全模式(不可hdfs写入)–>编写脚本:包含等待安全模式命令,以及hdfs写入命令–>使用另一个窗口执行脚本–>当安全模式退出时即可完成脚本中的hdfs写入
1.6.3 慢磁盘监控
如何发现慢磁盘?
1.通过心跳未联系时间(3s)
2.fio命令,测试磁盘的读写性能
命令 | 功能 |
sudo yum install -y fio | 安装测试命令 |
sudo fio -filename=/home/用户名/test.log -direct=1 -iodepth 1 -thread -rw=read -ioengine=psync -bs=16k -size=2G -numjobs=10 -runtime=60 -group_reporting -name=test_r | 顺序读测试 |
sudo fio -filename=/home/用户名/test.log -direct=1 -iodepth 1 -thread -rw=write -ioengine=psync -bs=16k -size=2G -numjobs=10 -runtime=60 -group_reporting -name=test_w | 顺序写测试 |
sudo fio -filename=/home/用户名/test.log -direct=1 -iodepth 1 -thread -rw=randwrite -ioengine=psync -bs=16k -size=2G -numjobs=10 -runtime=60 -group_reporting -name=test_randw | 随机写测试 |
sudo fio -filename=/home/用户名/test.log -direct=1 -iodepth 1 -thread -rw=randrw -rwmixread=70 -ioengine=psync -bs=16k -size=2G -numjobs=10 -runtime=60 -group_reporting -name=test_r_w -ioscheduler=noop | 混合随机读写 |
3.随机写相比较顺序写,写入位置不连贯,增加了寻址时间,效率下降
4.测试出慢磁盘不要慌,推荐使用慢磁盘存储冷数据,做到 合理存放
1.6.4 小文件归档
问题:
hdfs存储小文件时,按128M的块存储,小文件相比大文件更消耗nn大量内存,导致hdfs存储效率低下…
解决手段:
使用文件存档工具:HAR文件(存档文件)
步骤:
- 启动yarn:因为要提交作业执行程序将小文件读取,后写入到归档文件
- 把/input目录里面的所有文件归档成一个叫input.har的归档文件,并把归档后文件存储到/output路径下:
- hadoop archive -archiveName input.har -p /input /output
- 查看归档:
hadoop fs -ls /output/input.har
hadoop fs -ls har:///output/input.har
4 解归档文件:hadoop fs -cp har:///output/input.har/* /
5.上两步其实就是普通的hadoop命令加入了har协议
2 MapReduce调优
2.1 MR慢的原因
硬件和程序两个方面
计算机性能
1)CPU是否充足
2)内存是否够用
3)磁盘速度+冷热分离
4)网络带宽限制
I/O操作优化
1)数据倾斜:某个ReduceTask处理分区数据过多
2)Map运行时间太长,导致Reduce等待过久
3)小文件过多,MapTask并行度过高,资源不够
2.2 核心参数
- 自定义分区,将map的输出数据合理分担到多个maptask,可以减少数据倾斜
- 减少环形缓冲区溢写次数,即减少溢写的文件个数:
mapreduce.task.io.sort.mb,缓冲区大小默认100–>200
mapreduce.map.sort.spill.percent,开始反向溢写的阈值默认80–>90
- 增加每次Merge合并次数(前提,系统内存充足):
mapreduce.task.io.sort.factor默认10–>20
合理增加预聚合Combiner
可采用Snappy或LZO压缩
MapTask内存:
mapreduce.map.memory.mb默认1024M,前面使用压缩这里相应增加内存
同时保持MapTask堆内存(mapreduce.map.java.opts)和该值一致
适当增加MapTask的核数:mapreduce.map.cpu.vcores
异常重试:mapreduce.map.maxattempts默认是4适当修改
提高Reduce去Map中拉取数据的并行数:
mapreduce.reduce.shuffle.parallellcopies默认5–>10
拉取数据的缓存在Reduce内存占比:
mapreduce.reduce.shuffle.input.buffer.percent默认0.7–>0.8
数据在缓存占比多少开始向磁盘溢写:
mapreduce.reduce.shuffle.merge.percent默认0.66–>0.75
ReduceTask内存上限:
mapreduce.reduce.memory.mb默认1024适当提高
同时修改堆内存mapreduce.reduce.java.opts与其一致
ReduceTask核数:
mapreduce.reduce.cpu.vcores默认是1可提高到2-4个
异常重试:
mapreduce.reduce.maxattempts默认是4适当修改
MapTask完成的比例达到该值后才会为ReduceTask申请资源:
mapreduce.job.reduce.slowstart.completedmaps:0.05
任务超时时间:
mapreduce.task.timeout默认600000(10分钟)
Reduce能不用就省,没有reduce过程就可以不经过shuffle过程
2.3 Reduce数据倾斜
数据频率倾斜——某一个区域的数据量要远远大于其他区域。
数据大小倾斜——部分记录的大小远远大于平均值。
解决办法:
mapjoin/分区/预聚合/空值key打散
空值过多:
要么过滤空值,要么保留就得自定义分区,将空值加随机数打散,在二次聚合
map能先处理就先处理:Combiner或者MapJoin
分区并设置多个reduce个数
3 Yarn调优
3.1 核心参数
ResourceManager相关
1)处理调度器请求的线程数量:
yarn.resourcemanager.scheduler.client.thread-count
2)配置调度器:
yarn.resourcemanager.scheduler.class
NodeManager相关
1)NodeManager使用内存大小:
yarn.nodemanager.resource.memory-mb
2)使用CPU核数:
yarn.nodemanager.resource.cpu-vcores
3)是否将虚拟核数当作CPU核数:
yarn.nodemanager.resource.count-logical-processors-as-cores
4)虚拟核数和物理核数乘数,例如:4核8线程,该参数就应设为2:
yarn.nodemanager.resource.pcores-vcores-multiplier
5)是否让yarn自己检测硬件进行配置:
yarn.nodemanager.resource.detect-hardware-capabilities
6)是否开启物理内存检查限制container:
yarn.nodemanager.pmem-check-enabled
7)是否开启虚拟内存检查限制container:
yarn.nodemanager.vmem-check-enabled
8)虚拟内存物理内存比例:
yarn.nodemanager.vmem-pmem-ratio
Container容器相关
1)容器最小内存:
yarn.scheduler.minimum-allocation-mb
2)容器最大内存;
3)容器最小核数:
yarn.scheduler.minimum-allocation-vcores
4)容器最大核数;
容量调度器和公平调度器的使用:
详见:
yarn架构
4 Hadoop综合调优
以上参数配置和优化方法已经满足了大部分调优
这里最终汇总一下从三个方向包括四个具体步骤Hadoop小文件优化
4.1 数据源头
在数据采集的时候,就将小文件或小批数据合成大文件再上传HDFS
4.2 数据存储
Hadoop Archive文件归档,高效的将小文件放入HDFS块中的文件存档工具,能够将多个小文件打包成一个HAR文件,从而达到减少NameNode的内存使用
4.3 计算
CombineTextInputFormat用于将多个小文件在切片过程中生成一个单独的切片或者少量的切片。
开启uber模式.实现JVM重用:
让同一个Job的多个Task运行在一个JVM中,不必为每个Task都开启一个JVM。
开启uber模式:需在mapred-site.xml配置文件中添加以下参数:
1)开启uber模式:mapreduce.job.ubertask.enable
2)将最大的mapTask数量向下修改mapreduce.job.ubertask.maxmaps
3)将最大的reduce数量向下修改mapreduce.job.ubertask.maxreduces
4)将最大的输入数据量,默认使用dfs.blocksize 的值向下修改mapreduce.job.ubertask.maxbytes
该模式优势:
1)开启的容器数锐减:因为多个task共用一个容器
2)减少了开关jvm时间