HDFS 生产环境参数调优

作者: Ju4t

HDFS参数调优

jps

# 查看进行内存使用
jmap -heap PID

HDFS核心参数

  1. NameNode内存计算

每个文件块150byte,一台服务器128G内存为例,能存储多少文件块呢?

128 * 1024 * 1024 * 1024 / 150Byte 大约 9.1亿

G MB KB Byte

  1. Hadoop3.x系列,配置NameNode内存

具体修改:hadoop-env.sh

export HDFS_NAMENODE_OPTS = "-Dhadoop.security.logger=INFO,RFAS -Xmx1024m"
export HDFS_DATANODE_OPTS = "-Dhadoop.security.logger=ERROR,RFAS -Xmx4096m"

算法:

NameNode: 最小值1G,每增加100万个block,增加1G内存

DataNode:最小4G,block数,或者副本数升高都应该调大datanode的值,一个DataNode上的副本数低于400万,调为4G,超过400万,每增加100万,增加1G

分发、重启

NameNode 心跳并发配置

NameNode有一个工作线程池,用来处理不同的DataNode的并发心跳及客户端并发的元数据操作。

企业经验:

DataNode为3台,python计算

import math
print int(20*math.log(3)) # 3台datanode
21

hdfs-site.xml

<property>
    <name>dfs.namenode.handler.count</name>
  <value>21</value>
</property>

开启回收站配置

参数说明:

  1. 默认值fs.trash.interval=0,0表示禁用回收站;其他表示设置文件的存活时间;
  2. 默认值fs.trash.checkpoint.interval=0,检查回收站的间隔时间。如果为0,则该值设置和fs.trash.interval的参数相同;
  3. 要求fs.trash.checkpoint.interval>fs.trash.interval

启用回收站

修改core-site.xml,配置垃圾回收时间为1分钟

<property>
    <name>fs.trash.interval</name>
  <value>1</value>
</property>

查看回收站hdfs中 /user/hadoop/.Trash/....

注意:网页删除不走回收站

HDFS 集群压测

网络性能测试

python开启服务器

python -m SimpleHTTPServer

测试HDFS写性能

关闭yarn的虚拟内存检测

<property>
    <name>yarn.nodemanager.vmem-check-enabled</name>
  <value>false</value>
</property>

文件个数 = 集群CPU总核数 - 1(参数-nrFiles)

$ hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-3.2.2-tests.jar  TestDFSIO -write -nrFiles 5 -fileSize 128MB

...
2021-12-07 14:13:17,748 INFO fs.TestDFSIO: ----- TestDFSIO ----- : write
2021-12-07 14:13:17,748 INFO fs.TestDFSIO:             Date & time: Tue Dec 07 14:13:17 CST 2021
2021-12-07 14:13:17,748 INFO fs.TestDFSIO:         Number of files: 5
2021-12-07 14:13:17,749 INFO fs.TestDFSIO:  Total MBytes processed: 640
2021-12-07 14:13:17,749 INFO fs.TestDFSIO:       Throughput mb/sec: 4.48
2021-12-07 14:13:17,749 INFO fs.TestDFSIO:  Average IO rate mb/sec: 4.63
2021-12-07 14:13:17,749 INFO fs.TestDFSIO:   IO rate std deviation: 0.86
2021-12-07 14:13:17,749 INFO fs.TestDFSIO:      Test exec time sec: 79.51

分析:

一共参与测试的文件:5个文件 * 2个副本 = 10个 (如果测试文件不在集群内产生就是3副本,在集群内产生则是2个副本)

压测后的速度:4.48M/s * 10个文件 大约等44.8M/s

三台服务器的带宽: 12.5*3 = 37.5M/s

如果实测速度远远小于网络,并且实测速度不能满足工作需求,可以考虑采用固态硬盘或者增减磁盘个数。

测试HDFS读性能

$ hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-3.2.2-tests.jar  TestDFSIO -read -nrFiles 5 -fileSize 128MB

...
2021-12-07 14:16:38,705 INFO fs.TestDFSIO: ----- TestDFSIO ----- : read
2021-12-07 14:16:38,706 INFO fs.TestDFSIO:             Date & time: Tue Dec 07 14:16:38 CST 2021
2021-12-07 14:16:38,706 INFO fs.TestDFSIO:         Number of files: 5
2021-12-07 14:16:38,706 INFO fs.TestDFSIO:  Total MBytes processed: 640
2021-12-07 14:16:38,706 INFO fs.TestDFSIO:       Throughput mb/sec: 76.07
2021-12-07 14:16:38,706 INFO fs.TestDFSIO:  Average IO rate mb/sec: 76.36
2021-12-07 14:16:38,706 INFO fs.TestDFSIO:   IO rate std deviation: 4.83
2021-12-07 14:16:38,706 INFO fs.TestDFSIO:      Test exec time sec: 39.07

测试服务器台数只有3台,且3副本,所以读的都是本地,未走网络

HDFS多目录

NameNode 多目录

本地目录可以配置成多个,且每个目录存放的内容相同,增加了可靠性。

单纯的提供了NameNode的配置备份,生产环境可不配置,了解即可

vi pdfs-site.yaml

<property>
    <name>dfs.namenode.name.dir</name>
  <value>file://${hadoop.tmp.dir}/dfs/name1,file://${hadoop.tmp.dir}/dfs/name2</value>
</property>

生效:停止集群,删除所有节点下的data/ logs/

DataNode多目录

DataNode可以配置成多目录,每个目录存储的数据不一样(数据不是副本)

场景:硬盘不够了,增加硬盘

vi hdfs-site.xml

<property>
    <name>dfs.datanode.data.dir</name>
  <value>file://${hadoop.tmp.dir}/dfs/data1,file://${hadoop.tmp.dir}/dfs/data2</value>
</property>

集群磁盘之间的数据均衡(3.x新特性)

针对节点内部

# 生成均衡计划
hdfs diskbalancer -plan hadoop81

# 执行均衡计划
hdfs diskbalancer -execute hadoop82.plan.json

# 查看当前均衡任务的执行情况
hdfs diskbalancer -quer hadoop81

# 取消均衡计划
hdfs diskbalancer -cancel hadoop81.plan.json

HDFS集群扩容及缩容

添加白名单

# 未在白名单的,可以访问,但不能存储数据
vi $HADOOP_HOME/etc/hadoop/whitelist
hadoop81
hadoop82
hadoop83

touch blacklist

vi $HADOOP_HOME/etc/hadoop/hdfs-site.xml

<!-- 白名单 -->
<property>
    <name>dfs.hosts</name>
  <value>/opt/module/hadoop-3.2.2/etc/hadoop/whitelist</value>
</property>

<!-- 黑名单 -->
<property>
    <name>dfs.hosts.exclude</name>
  <value>/opt/module/hadoop-3.2.2/etc/hadoop/blacklist</value>
</property>

分发配置

生效:

  • 第一次添加,必须重启集群
  • 不是第一次,只需要刷新NameNode即可:hdfs dfsadmin -refreshNodes

服役新数据节点

动态增加服务器

准备好服务器后,删除hadoop下的 data/ logs/

单独启动hadoop84

$ hdfs --daemon start datanode
$ jps

$ yarn -edaemon start nodemanger

# 修改 白名单,把新节点加进去
vi $HADOOP_HOME/etc/hadoop/whitelist

# 刷新 dfs
hdfs dfsadmin -refreNodes

问题:多台时在那台上传的,就近存储原则,上传的节点一定包含一个副本,上传的越多,数据就越不均衡。

服务期间数据均衡

# 开启数据均衡 参数10,集群中各节点的磁盘空间利用率相差不超过10%,可更具实际情况调整
$ sbin/start-balance.sh -threshold 10

# 停止数据均衡
$ sbin/stop-balance.sh

# 由于HDFS需要启动单独的 Rebalance Server 来执行Rebalance,所以尽量不要在 NameNode上执行start-balance.sh,而是找一台比较空间的机器执行

黑名单退役旧节点

退役节点添加黑名单-避免数据再写入

vi hdfs-site.xml 设置黑名单配置,参考添加白名单

vi blacklist

# 同步backlist

# 刷新配置
hdfs dfsadmin -refreshNodes

# 验证
http://hadoop81:9870/
状态:
Decommissioning(退役中,将他的副本拷贝到其他节点,保证副本数)
Decommissioned (退役完成,所有的块已经复制完成)

# 仍然要执行均衡命令,保证工作的节点数据均衡
sbin/start-balance.sh

# 停止退役服务器的进程
hdfs --daemon stop datanode
yarn --daemon stop nodemanager

# 等待节点真正死掉,下线

HDFS存储优化

环境准备

演示纠删码和异构存储需要5台服务器

纠删码

场景:HDFS默认情况下,一个文件有3个副本,这样就提高了数据的安全性,但是也带来了2个点冗余开销。Hdoop3.x引入了纠删码,采用计算的方式,可以节省50%左右的存储空间。

相关命令

hdfs ec
hdfs ec -listPolicies

# 算法解释 https://www.bilibili.com/video/BV1Qp4y1n7EN?p=155&t=310.3
# RS-6-3-1024K (默认开启)

纠删码策略

场景:纠删码策略时给具体一个路径设置的。所以忘此路径下存放的文件都会执行此策略。默认RS-6-3-1024K,如果使用别的策略需要提前开启。

hdfs ec -enablePolicy -policy RS-6-3-1024K # 6+3需要9台服务器

# 验证
hdfs ec -listPolicies

# 创建一个文件夹
hdoop fs -mkdir /input

# 针对某个路径设置纠删策略
hdfs ec -setPolicy -path /input -policy RS-6-3-1024K

# 上传文件测试,查看副本数和存储的节点
# 数据单元 和 校验单元,所以副本数和设置的副本数显示不一样

# 删除下面的元数据,看看你能不能再web端继续下载
ok

异构存储(冷热数据的分离)

根据数据的冷热程度存到:

  • RAM_DISK:(内存镜像文件系统)
  • SSD:固态盘
  • DISK:机械盘
  • ARCHIVE:归档数据

存储策略:从Lazy_Persist到Cold下 由块到慢

策略ID 策略名称 副本分布 副本存储说明
15 Lazy_Persist RAM_DISK:1 DISK:n-1 1个存在RAM_DISK,其他存DISK
12 ALL_SSD SSD:n
10 One_SSD SSD:1 DISK:n-1
7 Hot(Default) DISK: n
5 Warm DISK:1 ARCHIVE: n-1
2 Cold ARCHIVE: n

异构存储Shell操作

# 查看当前有哪些储存策略可用
$ hdfs storagepolicies -listPolicies

# 为指定路径(数据存储目录)设置指定的存储策略
$ hdfs storagepolicies -setStoragePolicy -path xxx -policy xxx

# 获取指定路径的存储策略
$ hdfs storagepolicies -getStoragePolicy -path xxx

# 取消存储策略
$ hdfs storagepolicies -unsetStoragePolicy -path xxx

# 查看文件的块分布
$ hdfs fsck xxx -files -blocks -locations

# 查看集群节点
$ hadoop dfsadmin -report

测试环境准备

https://www.bilibili.com/video/BV1Qp4y1n7EN?p=158&spm_id_from=pageDriver

环境描述

服务器规模:5台

集群配置:副本数为2

存储规划:

节点 存储类型分配
Hadoop81 RAM_DISK,SSD
Hadoop82 SSD,DISK
Hadoop83 DISK,RAM_DISK
Hadoop84 ARCHIVE
Hadoop85 ARCHIVE

配置文件信息

  1. hadoop81的hdfs-site.xml
<!-- 删除原来的dfs.data.node.data.dir -->

<!-- 副本为2 -->
<property>
    <name>dfs.replication</name>
  <value>2</value>
</property>
<!-- 开启,默认也是开启的 -->
<property>
    <name>dfs.storeage.police.enabled</name>
  <value>true</value>
</property>
<!-- [SSD]、[RAM_DISK] 指定存储介质类型 -->
<property>
    <name>dfs.datanode.data.dir</name>
  <value>[SSD]file:///ope/module/hadoop-3.2.2/hdfsdata/ssd,[RAM_DISK]file:///ope/module/hadoop-3.2.2/hdfsdata/ram_disk</value>
</property>

每台配置不一样,都得按照规划单独配置,不能分发配置

重新格式化集群

# 停止集群
myhadoop.sh stop

# 删除所有节点的 data/ logs/
rm -rf data/ logs/

# 格式化
hdfs namenode -format

# 启动集群
myhadoop.sh start

# 上传文件
hdfs -mkdir /hdfsdata
hdfs -put xxx /hdfsdata

# 查看,所有数据都存在DISK,即默认
hdfs fsck /hdfsdata -files -blocks -locations

# 为指定路径(数据存储目录)设置指定的存储策略为WARM
hdfs storagepolicies -setStoragePolicy -path /hdfsdata -policy WARM
hdfs mover /hdfsdata # 按照策略自动移动文件,即生效

# 验证
hdfs fsck /hdfsdata -files -blocks -locations

Lazy_Persist 特殊说明:使用Lazy_Persist即可,推荐使用ALL_SSD

不推荐使用内存镜像,数据容易丢,保持如下即可

<!-- 内存镜像存储容量设置,值要大于块大小128M|256M -->
<property>
    <name>dfs.datanode.max.locked.memory</name>
  <value>0</value>
</property>

Linux系统也有限制

$ ulimit -a
...
max locked memory ... 64  (kb)

HDFS 故障排除

NameNode故障处理

进程挂了,数据丢了

jpsall

# 模拟故障
# 干掉进程
kill -9 <NAMENODE_PID>
# 删除dfs 数据
rm -rf data/dfs/name/*

# 启动进程
hdfs --daemon start namenode # 没有data数据,namenode启动不起来

# 查看log
cat logs/hadoop-hadoop-namenode-hadoop81.log
# 发现 namenode没有格式化

# 数据恢复,copy 2nn节点数据到namenode
cd data/dfs/name/
scp -r hadoop@hadoop83:/opt/module/hadoop-3.3.2/data/dfs/nameseccondary/* ./

# 再次启动namenode
hdfs --daemon start namenode

# 验证,namenode
jps

# 有30秒安全模式,无法删除

集群安全模式&磁盘修复

系统刚启动的时候会进入到安全模式,大约30秒

https://www.bilibili.com/video/BV1Qp4y1n7EN?p=160&t=153.5

数据修复时,可以设置安全模式,修复后退出安全模式

# 进入安全模式
hdfs dfsadmin -safemode enter

# 查看是否在安全模式
hdfs dfsadmin -safemode get

# 离开安全模式
hdfs dfsadmin -safemode leave

# 等待安全模式案状态(场景:阻塞操作)
hdfs dfsadmin -safemode wait

# 数据恢复,或者将提示的元删除,即可正常启动
# https://www.bilibili.com/video/BV1Qp4y1n7EN?p=160&t=1018.3
vi safamode.sh

#!/bin/bash
hdfs dfsadmin -safemode wait
hdfs dfs -put xx.txt /

chmod 777 safamode.sh

./safamode.sh

慢磁盘监控

https://www.bilibili.com/video/BV1Qp4y1n7EN?p=161&spm_id_from=pageDriver

现象:datanode 和 namenode 通讯时间厂

测试工具:

sudo yum install -y fio

# 执行顺序 读 测试

# 执行顺序 写 测试

# 随机写测试

# 混合随机读写测试

小文件归档

https://www.bilibili.com/video/BV1Qp4y1n7EN?p=162&spm_id_from=pageDriver

将小文件包裹起来,否则每个小文件暂用150个字节

# 归档 把input下的小文件归档到/optput
hadoop archive -archiveName input.har -p /input /output

# 查看
hadoop fs -ls /output/input.har

# 归档读取,加上协议即可看到小文件
fs -ls har:///output/input.har

# 恢复指定文件
hadoop fs -cp har:///output/input.har/xxx.txt /

HDFS一键迁移集群

https://www.bilibili.com/video/BV1Qp4y1n7EN?p=163&spm_id_from=pageDriver

Apache和Apache 集群间数据拷贝

  1. scp 拷贝
  2. hadoop distcp
# 都是NameNode
hadoop distcp hdfs://hadoop81:8020/user/test/hello.txt  hdfs://hadoop85:8020/user/test/hello.txt 

Apache和HDFS集群间的数据拷贝

生产经验

Mapreduce跑的慢

  1. 计算机性能:CPU、内存、磁盘、网络
  2. IO操作优化
  • 数据倾斜
  • Map运行时间太长,导致Reduce等待太久
  • 小文件过多

MapReduce常用调优参数

https://www.bilibili.com/video/BV1Qp4y1n7EN?p=165&spm_id_from=pageDriver

MapReduce阶段(上)

  1. 自定义分区,减少数据倾斜
  2. 减少溢写次数
  3. 增加每次Merge合并次数(根据内存情况调整,默认是10,可提高到20)
  4. 再不影响业务的前提条件下采用Combiner
  5. 减少磁盘IO,采用Snappy和LZO压缩
  6. 设置默认MapTask内存上限
  7. 控制MapTask堆内存大小
  8. 默认MapTask的CPU核数
  9. MapTask重试次数

MapReduce阶段(下)

  1. 每个Reduce去Map中拉取数据的并行行,默认5,提高到10
  2. Buffer大小占Reduce可用内存的比例,默认0.7,提高到0.8
  3. ...

image-20211212104928104

Mapreduce数据倾斜

https://www.bilibili.com/video/BV1Qp4y1n7EN?p=166&spm_id_from=pageDriver

减少数据倾斜的方法:

  • 首先检查是否空值造成的数据倾斜
  • 能在map阶段提前处理,最好在map阶段处理,如:combiner,mapjion
  • 设置多个reduce个数

Yarn 生产调优

https://www.bilibili.com/video/BV1Qp4y1n7EN?p=167&spm_id_from=pageDriver

Hadoop综合调优

小文件弊端

小文件解决方案

  1. 小文件尽量不要传到hdfs
  2. 存储方向 hadoop archive
  3. 计算方向 CombineTextInputFormat
  4. 开启uber模式,实现JVM重用,最多9次,(计算方向)类似于 slb 的连接复用
# https://www.bilibili.com/video/BV1Qp4y1n7EN?p=168&t=341.0
# uber 模式,验证:user mode 默认关闭
hadoop jar wc.jar /input /output

mapped-site.xml,小文件场景,参数都是忘下调

<!-- 开启uber模式 -->
<property>
    <name>mapreduce.job.ubertask.enable</name>
  <value>true</value>
</property>

<!-- uber模式中最大的maptask数量,可向下修改 -->
<property>
    <name>mapreduce.job.ubertask.maxmaps</name>
  <value>9</value>
</property>

<!-- uber模式中最大的reduce数量,可向下修改 -->
<property>
    <name>mapreduce.job.ubertask.maxreduces</name>
  <value>9</value>
</property>

<!-- uber模式中最大的数据输入量,默认使用dfs.blocksize值,只能小于块大小 -->
<property>
    <name>mapreduce.job.ubertask.maxbytes</name>
  <value></value>
</property>

测试MapReduce计算性能

https://www.bilibili.com/video/BV1Qp4y1n7EN?p=169&spm_id_from=pageDriver

注意:磁盘不超过150G尽量不要执行这段代码

  1. 使用RandomWrite来产生随数,每个节点运行10个map任务,每格map产生大于1G大小的二进制随机数
hadoop jar /opt/module/hadoop-3.2.2/share/hadoop/mapreduce/hadopp-mapreduce-examples-3.2.2.jar randomwriter random-data
  1. 执行Sort程序
hadoop jar /opt/module/hadoop-3.2.2/share/hadoop/mapreduce/hadopp-mapreduce-examples-3.2.2.jar sort random-data sorted-data
  1. 验证数据是否真正排序了
hadoop jar /opt/module/hadoop-3.2.2/share/hadoop/mapreduce/hadopp-mapreduce-client-jobclient-3.2.2-tests.jar testmapredsort -sortInput random-data-sortOutput sorted-data

jar包路径可能不完全正确,table 补全

https://www.bilibili.com/video/BV1Qp4y1n7EN?p=143&spm_id_from=pageDriver
https://www.bilibili.com/video/BV1Qp4y1n7EN?p=170&spm_id_from=pageDriver