Blog
hadoop-24 hadoop生产调优
HDFS 核心参数
NameNode内存生产配置
每个文件块大概150byte
- namenode最小值1G,每增加1000000个block,增加1G内存
- datanode最小值4G,block数或者副本数升高,都应该调大datanode的值
- 一个datanode上的副本总数低于4000000调为4G,超过4000000每增加1000000增加1G
hadoop-env.sh
export HDFS_NAMENODE_OPTS="-Dhadoop.security.logger=INFO,RFAS -Xmx1024m"
export HDFS_DATANODE_OPTS="-Dhadoop.security.logger=ERROR,RFAS -Xmx1024m"
NameNode心跳并发配置
namenode有一个工作线程池,用来处理不同DataNode的并发心跳,以及客户端并发的元数据操作
对于大集群或者有大量客户端的集群,通常需要增大该参数,默认值10
<property>
<name>dfs.namenode.handler.count</name>
<value>21</value>
</property>
开启回收站配置
开始回收站功能可以将删除的文件不超时的情况下,恢复原数据,起到防止误删除、备份等作用
开启回收站功能参数说明
- 默认值fs.trash.interval = 0 表示禁用回收站,其他值表示设置文件的存活时间
- 默认值fs.trash.checkpoint.interval = 0 检查回收站的间隔时间,如果该值为0,则该值设置和fs.trash.interval的参数值相等
- 要求fs.checkpoint.interval <= fs.trash.interval
启用回收站
- 修改core-site.xml 配置垃圾回收时间为1分钟
<property>
<name>fs.trash.interval</name>
<value>1</value>
</property>
- 查看回收站
- /user/atguigu/.Trash/...
- 通过网页上直接删除的文件不走回收站
- 通过程序删除的文件不会经过回收站,需要调用moveToTrash()才进入回收站
Trash trash = new Trash(conf)
trash.moveToTrash(path)
- 只有在命令行使用hadoop fs -rm 命令删除的文件才会走 回收站
- 恢复数据可以使用-mv 将数据移出来
HDFS集群压测
100Mbps单位是bit,10M/s单位是byte;1byte=8bit,100Mbps/8=12.5M/s
开启简单http服务
python -m SimpleHTTPServer
写测试
hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-3.1.3-tests.jar TestDFSIO -write -nrFiles 5 -fileSize 128MB
-nrFiles:生成mapTask的数量,一般是集群中(CPU核数-1)
- Throughput=所有数据累加/总时间
- Average IO rate = 所有平均速度的平均值
结果分析:
由于一个副本在本地,所以该副本不参与测试
- 一共参与测试的文件:5个文件 * 2个副本 = 10个
- 压测后的速度3.84
- 实测速度:3.84M/s * 10个文件 = 38M/s
- 三台服务器的带宽: 12.5 + 12.5 + 12.5 = 37.5M/s
所有网络资源都已经用满,如果客户端不在集群节点,那就三个副本都参与计算
读测试
hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-3.1.3-tests.jar TestDFSIO -read -nrFiles 5 -fileSize 128MB
- 就近读取本地副本数据,不走网络
HDFS多目录
NameNode多目录配置
namenode本地目录可以配置成多个,且每个目录存放内容相同,增加了可靠性
具体配置如下:
- hdfs-site.xml
<property>
<name>dfs.namenode.name.dir</name>
<value>file://${hadoop.tmp.dir}/dfs/name1,file://${hadoop.tmp.dir}/dfs/name2</value>
</property>
- 因为每台服务器节点的磁盘情况不同,所以这个配置配完之后,可以选择不分发
- 停止集群,删除三台节点data和logs中所有数据
rm -rf data/ logs/
格式化集群并启动
hdfs namenode -format
start-dfs.sh
DataNode多目录配置
DataNode可以配置成多个目录,每个目录存储的数据不一样(数据不是副本)
具体配置如下: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>
磁盘数据均衡
生产环境,由于硬盘空间不足,往往需要增加一块硬盘,刚加载的硬盘没有数据,可以执行磁盘数据均衡命令
- 生成均衡计划
hdfs diskbalancer -plan hadoop103
执行均衡计划
hdfs diskbalancer -execute hadoop103.plan.json
查看当前均衡任务的执行情况
hdfs diskbalancer -query hadoop103
取消均衡任务
hdfs diskbalancer -cancel hadoop103.plan.json
HDFS集群扩容即缩容
添加白名单
- 白名单:表示在白名单的主机IP地址可以,用来存储数据
- 企业中配置白名单,可以尽量防止黑客恶意访问攻击
配置白名单步骤如下:
- 在namenode节点的hadoop/etc/hadoop目录下分别创建whitelist和blacklist文件
- 创建白名单,添加hadoop102和hadoop103节点
vim whitelist
# 添加
hadoop102
hadoop103
- 创建黑名单 touch blacklist
- 配置hdfs -site.xml
<!-- 白名单 -->
<property>
<name>dfs.hosts</name>
<value>/opt/module/hadoop-3.1.3/etc/hadoop/whitelist</value>
</property>
<!-- 黑名单 -->
<property>
<name>dfs.hosts.exclude</name>
<value>/opt/module/hadoop-3.1.3/etc/hadoop/blacklist</value>
</property>
- 分发配置文件
- xsync whitelist
- 第一次添加白名单必须重启集群,不是第一次,只需要刷新namenode节点即可
myhadoop.sh stop
myhadoop.sh start
- 104不再被当做存储数据副本节点
- 白名单添加hadoop104
- 刷新namenode
- 刷新所有namenode datanode节点
hdfs dfsadmin -refreshNodes
添加新的数据节点
环境准备:
- 在hadoop100上再克隆一台主机hadoop105
- 修改ip地址和主机名称
- 将102下的hadoop和jdk拷贝到hadoop105
scp -r /opt/module/hadoop-3.1.3/ atguigu@hadoop105:/opt/module
scp -r /opt/module/jdk1.8.0_212 atguigu@hadoop105:/opt/module
拷贝环境变量
sudo scp /etc/profile.d/myenv.sh root@hadoop105:/etc/profile.d/
- 保留JDK和HADOOP_HOME环境变量
- source /etc/profile
- ssh无密访问
- hadoop102(namenode) -> hadoop105
- hadoop102(resourcemanager) -> hadoop105
- ssh-copy-id hadoop105
- 删除hadoop105中hadoop文件夹下的data和logs文件夹
rm -rf data/ logs/
启动hadoop105上的datanode和nodemanager
hdfs --daemon start datanode
yarn --daemon start nodemanager
- 如果未配置白名单则立即生效
- 配置白名单
- whitelist增加hadoop105并分发
- hdfs dfsadmin -refreshNodes
节点间数据均衡
- 开启数据均衡命令
- threshold 代表集群中各个节点的磁盘空间利用率相差不超过10%
sbin/start-balancer.sh threshold 10
通知数据均衡命令
sbin/stop-balancer.sh
- 由于HDFS需要单独启动单独的Rebalance Server 来执行Rebanlance操作,所以尽量不要在NamoNode上执行start-balancer.sh 尽可能找一台空闲的机器
退役一个数据节点
把当前节点副本复制给其他节点,停止该节点存储数据
blacklist添加hadoop105
- hdfs-site.xml
<!-- 黑名单 -->
<property>
<name>dfs.hosts.exclude</name>
<value>/opt/module/hadoop-3.1.3/etc/hadoop/blacklist</value>
</property>
- 分发配置文件
- 第一次添加黑名单必须重启集群。不是第一次则只需要刷新NameNode节点
hdfs dfsadmin -refreshNodes
手动停止hadoop105上datanode和nodemanager进程
hdfs --daemon stop datanode
yarn --daemon stop nodemanager
如果数据不均衡,可以用命令实现集群的再平衡
sbin/start-balancer.sh threshold 10
查看数据块存储信息
hdfs fsck /input -files -blocks -locations
HDFS故障排除
NameNode故障处理
namenode进程挂了并且存储数据也丢失了,如何恢复namenode
- kill -9 namenode进程
- 删除hadoop/data/dfs/name/下所有namenode数据
- 切换到hadoop104(secondarynamenode)节点 查看2NN信息
/opt/module/hadoop-3.1.3/data/dfs/namesecondary
复制2NN数据到hadoop102 NN节点
scp -r atguigu@hadoop104:/opt/module/hadoop-3.1.3/data/dfs/namesecondary/* /opt/module/hadoop-3.1.3/data/dfs/name
- 生成环境一般不用这个方法 ,使用HA高可用 两个NN
集群安全模式和磁盘修复
安全模式:文件系统只接受读数据请求,而不接受删除、修改等变更请求
进入安全模式场景:
- namenode在加载镜像文件和编辑日志处于安全模式
- 集群启动中
- namenode在接收datanode注册时,处于安全模式
退出安全模式条件:
- dfs.namenode.safemode.min.datanodes
- 最小可用datanode数量,默认0
- dfs.namenode.safemode.threshold-pct
- 副本数达到最小要求的block占系统总block百分百,默认0.999f (只允许丢一个块)
- dfs.namenode.safemode.extension
- 稳定时间,默认30秒
基本语法
- 查看安全模式
- hdfs dfsadmin -safemode get
- 进入安全模式状态
- hdfs dfsadmin -safemode enter
- 离开安全模式
- hdfs dfsadmin -safemode leave
- 等待安全模式
- hdfs dfsadmin -safemode wait
磁盘修复
删除三个节点上两个块数据
cd /opt/module/hadoop-3.1.3/data/dfs/data/current/BP-1230679643-192.168.10.102-1618410754513/current/finalized/subdir0/subdir0
rm -rf rm -rf blk_1073741829 rm -rf blk_1073741829.meta rm -rf blk_1073741828 rm -rf blk_1073741828.meta
- 重启集群(一直安全模式)
- 离开安全模式命令
- hdfs dfsadmin -safemode leave
- 接着告知文件块错误
- 按照上面提示删除对应路径文件即可
慢磁盘查找
- 心跳时间长
- fio命令,测试磁盘读写性能
sudo yum install -y fio
# 顺序读
sudo fio -filename=/home/atguigu/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/atguigu/test.log -direct=1 -iodepth 1 -thread -rw=write -ioengine=psync -bs=16k -size=2G -numjobs=10 -runtime=60 -group_reporting -name=test_r
- -rw=randwrite随机写
- -rw=randrw混合随机速写
- -rwmixread=70
小文件归档
大量小文件会耗尽NameNode中的大部分内存,存储小文件所需要的磁盘容量和数据块的大小无关
解决存储小文件办法之一:
- HDFS存档文件或HAR文件,是一个更高效的文件存档工具,它将文件存入HDFS块,在减少NameNode内存使用的同时,运行文件进行透明的访问
- 启动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
- 解归档文件
- 将归档文件中words.txt拷贝到根目录
hadoop fs -cp har:///output/input.har/words /
HDFS集群迁移
apache和apache集群间数据拷贝
- scp实现两个远程主机之间文件复制
- 采用distcp命令实现两个hadoop集群之间的递归数据复制
bin/hadoop distcp hdfs://hadoop102:8020/xxx/xx.txt hdfs://hadoop105:8020/xxx/xx.txt
apache和CDH集群间数据拷贝
MapReduce生成经验
mapreduce跑的慢的原因
- 计算机性能
- I/O操作优化
- 数据倾斜,多个map发送到一个reduce
- map运行时间太长,导致reduce等待太久
- 小文件过多
MapReduce常用参数调优
MapTask阶段调优:
- 自定义分区,减少数据倾斜
- 定义类,继承Partitioner接口,重写getPartition方法
- 减少溢写的次数
- mapreduce.task.io.sort.mb
- Shuffle的环形缓冲区大小,默认100m,可以提高到200m
- mapreduce.map.sort.spill.percent
- 环形缓冲区溢出的阈值,默认80% 可以提高到90%
- 增加每次Merge合并次数
- mapreduce.task.io.sort.factor默认10,可以提高到20
- 在不影响业务结果的前提条件下,可以提前采用Combiner
- job,setCombinerClass(xxxReducer.class)
- 为了减少磁盘IO,可以采用Snappy或者LZO压缩
- conf.setBoolean("mapreduce.map.output.compress", true)
- conf.setClass("mapreduce.map.output.compress.codec", SnappyCodec.class, CompressionCodec.class)
- mapreduce.map.memory.mb 默认MapTask内存上线1024MB
- 可以根据128M数据对应1G内存原则提高该内存
- mapreduce.map.java.opts:控制MapTask堆内存大小,如果内存不够,报OutOfMemoryError
- mapreduce.map.cpu.vcores 默认MapTask的CPU核数1,计算密集型任务可以增加CPU核数
- 异常重试
- mapreduce.map.maxattempts每个MapTask最大重试次数,一旦重试次数超过该值,则认为MapTask运行失败,默认值:4 ,根据机器性能适当提高。
Reduce阶段调优:
- mapreduce.reduce,shuffle.parallelcopies
- 每个Reduce去Map中拉取数据的并行数,默认5,可以提高到10
- mapreduce.reduce.shuffle.input.buffer.percent
- Buffer大小占Reduce可用内存的比例,默认0.7,可以提高到0.8
- mapreduce.reduce.shuffle.merge.merge.percent
- Buffer中的数据达到多少比例开始写入磁盘,默认0.66,可以提高到0.75
- mapreduce.reduce.memory.mb默认ReduceTask内存上线1024MB,根据128M数据对应1G内存原则,适当提高内存到4-6G
- mapreduce.reduce.java.opts:控制ReduceTask堆内存大小,不够则包OM错误
- mapreduce.reduce.cpu.vcores默认ReduceTask的CPU核数1个,可以提高到2-4个
- mapreduce.reduce.maxattempts每个Reduce Task最大重试次数,默认4
- mapreduce.job.reduce.slowstart.completedmaps
- 当MapTask完成的比例达到该值后会为ReduceTask申请资源,默认0.05
- mapreduce.task.timeout
- 如果一个Task一定时间内没有任何进入也没有输出数据则认为该Task处于Block状态,为防止用户程序永远Block卡住不退出,则设置一个超时时间,默认600000(10分钟)
- 如果程序对每条输入数据的处理时间过长,建议将该参数调大
减少数据倾斜的方法
- 首先检查是否空值过多,造成的数据倾斜
- 生产环境,可以直接过滤掉空值
- 如果想保留空值,就自定义分区,将空值加随机数打散,最后再二次聚合
- 能在map阶段提前处理,最好在map阶段处理,如Combiner,MapJoin
- 设置多个reduce个数