Hadoop 优化|全面调优攻略 | HDFS、MapReduce、YARN 性能提升秘诀 | 专家实战分享!
HDFS 调优
NameNode 内存
Hadoop2.x 系列,NN 内存默认 2000M,根据服务器(以 4G 为例)的 3/4 来配:
Hadoop3.x 系列,hadoop-env.sh 文件中说明了内存自动分配。通过命令 jmap -heap < jps 查看到的进程的 PID >可知 NameNode 和 DataNode 占用内存都是自动分配的,且相等。不是很合理。
手动配置: hadoop-env.sh
NameNode 心跳并发
NameNode 有一个工作线程池,用来处理不同 DataNode 的并发心跳以及客户端并发的元数据操作。
线程数 dfs.namenode.handler.count 默认是 10,按企业经验 hdfs-site.xml 中该值设为
开启回收站
将删除的文件在不超时的情况下恢复,防止误删:
修改 core-site.xml 中回收时间 fs.trash.interval 值为 60,以及检查间隔 fs.trash.checkpoint.interval 值为小于回收时间
查看回收站:HDFS 中路径:/user/用户名/.Trash/…
web 端删除不经过回收站,或者通过程序删除只有使用 moveToTrash() 才走回收站,此外 shell 操作命令使用 hadoop fs -rm 才走回收站
恢复数据的话将回收站路径下文件移动即可
集群压测
考虑到 Java 后台拉取的数据用多久能上传到集群,以及从 HDFS 上拉取数据的时间,因此对集群压测以测出 HDFS 的读写性能
说明:HDFS 的读写性能主要受限于网络和磁盘.
写性能测试
前提:设置集群网速为 100Mbps 单位是 bit;换算后为 12.5M/s
测试步骤:
1.yarn-site.xml 中设置关闭虚拟内存检测(避免 centos 和 jdk 的不兼容),分发
2.向 HDFS 写 10 个 128M 的文件(文件数>两个节点总核数就行,保证每个节点都有任务)
3.命令:
结果分析:
忽略客户端所在节点的本地副本,参与测试的一共 20 个文件写入集群
压测后的速度(单个文件的写速度):1.61
实测速度:1.61*20=32M/s
三台服务器带宽:12.5*3 略大于实测速度
结论:说明所有网络资源已用满,因此写速度主要受限于网络传输速度
读性能测试
将上面 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
测试完毕,收尾,删除测试数据
hadoop jar /opt/module/hadoop-3.1.3/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-3.1.3-tests.jar TestDFSIO -clean
结论:测试节点存在文件副本,就近读取,读的本地磁盘,没经过网络,读速度不受网络限制,只受磁盘读写速度限制。
多目录
NameNode 多目录配置
NN 本地目录配置为多个,每个目录存放内容相同
说明:备份了 nn,提高了可靠性,但不是高可用,nn 所在节点挂掉集群仍无法工作
步骤:
hdfs-site.xml 中添加内容,将 dfs.namenode.name.dir 修改为两个目录
停止集群,删除所有节点的 date 和 logs 中数据
格式化 nn 后启动集群
DataNode 多目录配置
DN 可以配置成多目录,不同于 nn 的备份,dn 多目录存放不同数据,解决磁盘空间不足问题。
步骤:
hdfs-site.xml 中添加内容,将 dfs.datanode.data.dir 修改为两个目录
将该配置文件适量分发,因每个服务器配置可能不同,分发请慎重
磁盘间数据均衡
增加一块硬盘。刚加载的硬盘没有数据时,可以执行磁盘数据均衡命令。
说明:这是 Hadoop3.x 新特性,单节点内部磁盘均衡。
步骤:
生成均衡计划:
hdfs diskbalancer -plan hadoop103
执行均衡计划:
hdfs diskbalancer -execute hadoop103.plan.json
查看当前均衡任务的执行情况:
hdfs diskbalancer -query hadoop103
取消均衡任务:
hdfs diskbalancer -cancel hadoop103.plan.json
集群扩容及缩容
添加白名单
在白名单的主机 IP 地址才可以用来存储数据。可以尽量防止黑客恶意访问攻击。
步骤:
在 hadoop 软件包下的 etc/hadoop 目录下创建 whitelist 和 blacklist 文件
whitelist 文件中加入集群节点的 ip 或主机名(映射)
hdfs-site.xml 中增加 dfs.hosts 配置参数为 whitelist 路径并分发
第一次创白名单得重启集群,否则只需刷新 nn 节点(hdfs dfsadmin -refreshNodes)
服役新服务器
动态增加服务器,不重启集群即可实现服役新服务器,主要解决数据节点容量不足。
步骤:
环境准备:修改新主机的 ip、主机名;将软件包目录和环境变量脚本拷贝过来;清空,data 和 log 目录下的数据;配置和其他节点的无密登录
服役新节点:启动该节点的 datanode 和 nodemanager 的后台进程
白名单中增加待加入的节点并分发
刷新 nn
服务器间数据均衡
如果常在某个节点提交任务,由于数据本地性原则,该节点数据量过多,造成数据节点间量的 差距,或者,新服役的服务器数据量比较少,需要执行集群均衡命令。
开启数据均衡命令:start-balancer.sh -threshold 10(10 代表的是集群中各个节点的磁盘空间利用率相差不超过 10%,可根据实际情况进行调整)
停止数据均衡命令:stop-balancer.sh
黑名单退役服务器
步骤:
在 hadoop 软件包目录的 etc/hadoop 目录下编辑 blacklist 文件:添加要退役的节点
在 hdfs-site.xml 配置文件中增加 dfs.hosts.exclude 配置参数,分发
同白名单一样,第一次创黑名单需重启集群,否则刷新 nn 节点
说明:
节点退役时,web 界面可以看到,退役节点的状态为 decommission in progress(退役中),说明数据节点正在复制块到其他节点
此操作是保证副本数满足要求, 如果副本数是 3,服役的节点小于等于 3,是不能退役成功的,需要修改副本数后才能退役
如果节点间数据不均衡,可以用命令再平衡
存储优化
纠删码
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 个单元才看出效果
易构存储
异构存储,又叫冷热数据分离,它不同于纠删码的单副本,它是给 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,虽然它也可调,但是易出错,不推荐,所以别使用该策略最好
故障排除
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 解决)
集群安全模式 &磁盘修复
安全模式:文件系统只接受读数据请求,而不接受删除、修改等变更请求
进入安全模式场景:
nn 在加载镜像文件和编辑日志期间处于安全模式;
NameNode 再接收 DataNode 注册时,处于安全模式
退出安全模式条件(以下需全部满足):
可用数据节点>0
最多丢失一块 block 的所有副本
满足前两个条件并稳定 30s
相关命令
案例 1:启动集群进入安全模式
启动集群后立即(30s 以内)来到集群 web 界面删除数据,提示集群处于安全模式
案例 2:硬盘修复
删除两个块的所有副本,重启集群–>web 界面提示块数量对不上警告–>输入命令离开安全模式–>依然警告–>不管则每次安全模式开启时都会警告–>解决办法:将警告信息中的已经丢失的文件块对应的元数据删除,或者联系磁盘厂家修复–>集群正常
案例 3:模拟等待安全模式
先进入安全模式(不可 hdfs 写入)–>编写脚本:包含等待安全模式命令,以及 hdfs 写入命令–>使用另一个窗口执行脚本–>当安全模式退出时即可完成脚本中的 hdfs 写入
小文件归档
问题:
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
解归档文件:
hadoop fs -cp har:///output/input.har/* /
上两步其实就是普通的 hadoop 命令加入了 har 协议
MapReduce 调优
MR 慢的原因(计算机性能)
CPU 是否充足
内存是否够用
磁盘速度+冷热分离
网络带宽限制
I/O 操作优化
数据倾斜:某个 ReduceTask 处理分区数据过多
Map 运行时间太长,导致 Reduce 等待过久
小文件过多,MapTask 并行度过高,资源不够
核心参数
自定义分区,将 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 中拉取数据的并行数:
拉取数据的缓存在 Reduce 内存占比:
数据在缓存占比多少开始向磁盘溢写:
ReduceTask 内存上限:
同时修改堆内存 mapreduce.reduce.java.opts 与其一致
ReduceTask 核数:
异常重试:
mapreduce.reduce.maxattempts 默认是 4 适当修改
MapTask 完成的比例达到该值后才会为 ReduceTask 申请资源:
mapreduce.job.reduce.slowstart.completedmaps:0.05
任务超时时间:
Reduce 能不用就省,没有 reduce 过程就可以不经过 shuffle 过程
Reduce 数据倾斜
数据频率倾斜——某一个区域的数据量要远远大于其他区域。
数据大小倾斜——部分记录的大小远远大于平均值。
解决办法:
mapjoin/分区/预聚合/空值 key 打散
空值过多:要么过滤空值,要么保留就得自定义分区,将空值加随机数打散,在二次聚合 map 能先处理就先处理 Combiner 或者 MapJoin 分区并设置多个 reduce 个数
Yarn 调优
ResourceManager 相关处理调度器请求的线程数量:
配置调度器:
NodeManager 相关
1.NodeManager 使用内存大小:
2.使用 CPU 核数:
3.是否将虚拟核数当作 CPU 核数:
4.虚拟核数和物理核数乘数,例如:4 核 8 线程,该参数就应设为 2:
5.是否让 yarn 自己检测硬件进行配置:
6.是否开启物理内存检查限制 container:
7.是否开启虚拟内存检查限制 container:
8.虚拟内存物理内存比例:
Container 容器相关
1.容器最小内存:
2.容器最大内存;
3.容器最小核数:
Hadoop 综合调优
以上参数配置和优化方法已经满足了大部分调优
这里最终汇总一下从三个方向包括四个具体步骤 Hadoop 小文件优化
数据源头
在数据采集的时候,就将小文件或小批数据合成大文件再上传 HDFS
数据存储
Hadoop Archive 文件归档,高效的将小文件放入 HDFS 块中的文件存档工具,能够将多个小文件打包成一个 HAR 文件,从而达到减少 NameNode 的内存使用
计算
CombineTextInputFormat 用于将多个小文件在切片过程中生成一个单独的切片或者少量的切片。
开启 uber 模式.实现 JVM 重用:
让同一个 Job 的多个 Task 运行在一个 JVM 中,不必为每个 Task 都开启一个 JVM。
开启 uber 模式:需在 mapred-site.xml 配置文件中添加以下参数:
开启 uber 模式:mapreduce.job.ubertask.enable
将最大的 mapTask 数量向下修改 mapreduce.job.ubertask.maxmaps
将最大的 reduce 数量向下修改 mapreduce.job.ubertask.maxreduces
将最大的输入数据量,默认使用 dfs.blocksize 的值向下修改 mapreduce.job.ubertask.maxbytes
该模式优势:
开启的容器数锐减:因为多个 task 共用一个容器
减少了开关 jvm 时间
以上就是今天分享的全部内容。
如果你想了解更多关于:Cloudera 系统环境准备、基础环境安装、集群部署以及应用组件安装等全方位的技术的问题。例如:从环境搭建/集群部署,内存扩容/问题排查,数据迁移等助你轻松应对数据管理的复杂性。可以联系我:15928721005
感谢你的阅读,如果喜欢我的文字,可以持续关注我,会陆续为你更新更多干货小知识。
评论