HDFS核心参数
NameNode,DataNode内存配置
查看NameNode,DataNode占用内存
jps jmap -heap 2611 jmap -heap 2744
经验
# NameNode最小值1G,每增加100w个block,增加1G内存 # DataNode最小值4G,副本总数超过400w时,每增加100w,增加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准备多少线程合适
经验:20*log(Cluster Size)
具体修改:
hdfs-site.xml
<!-- 默认值为10,如果集群有3台机器,根据公式20*log(3)=21 --> <property> <name>dfs.namenode.handler.count</name> <value>21</value> </property>
开启回收站配置(防止误删)
具体修改:
core-site.xml
<!-- 默认值为0,表示禁用回收站,设置为1表示垃圾回收时间为1分钟 --> <property> <name>fs.trash.interval</name> <value>1</value> </property>
注意事项
# 网页上直接删除的文件不会走回收站 # 通过java代码,如果没调用moveToTrash(),也不会走回收站 # 只有通过hadoop fs -rm命令删除的文件才会走回收站 # 回收站目录:/user/lixuan/.Trash/...
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>
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 node01
执行均衡计划
hdfs diskbalancer -execute node01.plan.json
查看计划执行情况
hdfs diskbalancer -query node01
取消均衡任务
hdfs diskbalancer -cancel node01.plan.json
服务器间数据均衡
开启数据均衡(集群中各节点的磁盘利用率相差不超过10%)
sbin/start-balancer.sh -threshold 10
停止数据均衡
sbin/stop-balancer.sh
注意:找一台比较闲的机器执行start-banacer,不要再NameNode上执行
集群扩容和减配
添加白名单
在NameNode节点下的
/opt/module/hadoop-3.1.3/etc/hadoop
目录下分别创建whitelist文件和blacklist文件在whitelist中添加集群的主机名,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>
分发配置文件并重启集群
向白名单中间增加机器后要刷新NameNode
hdfs dfsadmin -refreshNodes
服役新服务器
- 从原先的集群中克隆一台机器
- 修改ip地址和主机名
- 删除新机器的Hadoop的data和log数据
- 配置免密登录
- 向白名单中添加新节点
- 分发白名单
- 刷新NameNode
黑名单退役服务器
- 在blacklist中加入要退役的主机名
- 分发黑名单
- 刷新NameNode
- 注意:如果服役的节点数小于副本数,需要修改副本数后才能成功退役
- 如果退役后数据不均衡,需要重新均衡
HDFS异构存储(冷热数据分离)
存储策略
策略ID | 策略名称 | 副本分布 |
---|---|---|
15 | Lazy_Persist | RAM_DISK:1, DISK:n-1 |
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
查看文件块的分布
bin/hdfs fsck xxx -files -blocks -locations
查看集群节点
hadoop dfsadmin -report
HDFS故障处理
NameNode故障处理
- 将SecondaryNameNode中的数据拷贝到原NameNode存储数据目录
- 重启NameNode
慢磁盘监控
通过心跳未联系时间,超过3秒说明有异常
通过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_w # 随机写测试 sudo fio -filename=/home/atguigu/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/atguigu/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
小文件归档
# 启动yarn进程
# 把/input目录里面的所有文件归档成一个叫input.har的归档文件,并把归档后文件存储到/output路径下
hadoop archive -archiveName input.har -p /input /output
# 查看归档
hadoop fs -ls har:///output/input.har
# 解归档文件
hadoop fs -cp har:///output/input.har/* /
MapReduce经验
MapReduce跑的慢的原因
- 计算机性能
- 数据倾斜
- Map和Reduce数设置不合理
- Map运行时间太长,导致Reduce等待过久
- 小文件过多
- 大量的不可切片的超大压缩文件
- Spill次数过多
- Merge次数过多
MapReduce优化方法
数据输入
- 合并小文件
- 采用CombineTextInputFormat来作为输出
Map阶段
- 减少溢写(Spill)次数
- 通过调整
mapreduce.task.io.sort.mb
及mapreduce.map.sort.percent
参数值,增大触发Spill的内存上限,减少Spill次数,从而减少磁盘IO
- 通过调整
- 减少合并(Merge)次数
- 通过调整
mapreduce.task.io.sort.factor
参数,增大Merge的文件数目,减少Merge的次数
- 通过调整
- 在Map之后,不影响业务逻辑的前提下,先进行Combine处理
Reduce阶段
- 合理设Map和Reduce数
- 设置Map、Reduce共存
- 调整
mapreduce.job.reduce.slowstart.completedmaps
参数 - 使Map运行到一定程度后,Reduce也开始运行,减少Reduce的等待时间
- 调整
- 规避使用Reduce
- Reduce在用于连接数据集的时候会产生大量分网络消耗
- 合理设置Reduce端的Buffer
- 默认情况下,数据达到一个阈值的时候,Buffer中的数据就会写入磁盘,然后Reduce会从磁盘中获得所有数据,消耗了IO
mapreduce.reduce.input.buffer.percent
默认为0,设置大于0的值,会保存指定比例的内存将数据直接从Buffer中拿给Reduce使用
IO传输
- 采用数据压缩的方式,snappy、LZO
数据倾斜问题
过滤空值
抽样个范围分区
自定义分区
Combiner
采用Map Join,尽量避免Reduce Join
小文件优化
数据采集的时候,将小文件合成大文件再上传HDFS
将多个小文件打包成Har文件,从而减少NameNode内存的使用
使用
CombineTextInputFormat
再切片中将小文件转化为更少的切片开启uber模式,实现JVM重用
mapred-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>1</value> </property> <!-- uber模式中最大的输入数据量,默认使用dfs.blocksize 的值,可向下修改 --> <property> <name>mapreduce.job.ubertask.maxbytes</name> <value></value> </property>
Yarn经验
常用调优参数
ResourceManager相关
# ResourceManager处理调度器请求的线程数量 yarn.resourcemanager.scheduler.client.thread-count # 配置调度器 yarn.resourcemanager.scheduler.class
NodeManager相关
# NodeManager使用内存数 yarn.nodemanager.resource.memory-mb # NodeManager为系统保留多少内存,和上一个参数二者取一即可 yarn.nodemanager.resource.system-reserved-memory-mb # NodeManager使用CPU核数 yarn.nodemanager.resource.cpu-vcores # 是否将虚拟核数当作CPU核数 yarn.nodemanager.resource.count-logical-processors-as-cores # 虚拟核数和物理核数乘数,例如:4核8线程,该参数就应设为2 yarn.nodemanager.resource.pcores-vcores-multiplier # 是否让yarn自己检测硬件进行配置 yarn.nodemanager.resource.detect-hardware-capabilities # 是否开启物理内存检查限制container yarn.nodemanager.pmem-check-enabled # 是否开启虚拟内存检查限制container yarn.nodemanager.vmem-check-enabled # 虚拟内存物理内存比例 yarn.nodemanager.vmem-pmem-ratio
Container相关
# 容器最小内存 yarn.scheduler.minimum-allocation-mb # 容器最大内存 yarn.scheduler.maximum-allocation-mb # 容器最小核数 yarn.scheduler.minimum-allocation-vcores # 容器最大核数 yarn.scheduler.maximum-allocation-vcores
容量调度器的使用
<!-- 指定多队列,增加hive队列 -->
<property>
<name>yarn.scheduler.capacity.root.queues</name>
<value>default,hive</value>
<description>
The queues at the this level (root is the root queue).
</description>
</property>
<!-- 降低default队列资源额定容量为40%,默认100% -->
<property>
<name>yarn.scheduler.capacity.root.default.capacity</name>
<value>40</value>
</property>
<!-- 降低default队列资源最大容量为60%,默认100% -->
<property>
<name>yarn.scheduler.capacity.root.default.maximum-capacity</name>
<value>60</value>
</property>
<!-- 指定hive队列的资源额定容量 -->
<property>
<name>yarn.scheduler.capacity.root.hive.capacity</name>
<value>60</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.hive.user-limit-factor</name>
<value>1</value>
</property>
<!-- 指定hive队列的资源最大容量 -->
<property>
<name>yarn.scheduler.capacity.root.hive.maximum-capacity</name>
<value></value>
</property>
<property>
<name>yarn.scheduler.capacity.root.hive.state</name>
<value>RUNNING</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.hive.acl_submit_applications</name>
<value>*</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.hive.acl_administer_queue</name>
<value>*</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.hive.acl_application_max_priority</name>
<value>*</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.hive.maximum-application-lifetime</name>
<value>-1</value>
</property>
<property>
<name>yarn.scheduler.capacity.root.hive.default-application-lifetime</name>
<value>-1</value>
</property>
# 配置完成后,刷新队列
yarn rmadmin -refreshQueues
# 通过API向Hive队列提交任务
configuration.set("mapreduce.job.queuename","hive");
调优案例
需求
- 从1G数据中,统计每个单词出现次数
- 服务器3台,每台配置4G内存,4核CPU,4线程
需求分析
1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster
平均每个节点运行10个 / 3台 ≈ 3个任务(4 3 3)
HDFS调优
hadoop-env.sh
export HDFS_NAMENODE_OPTS="-Dhadoop.security.logger=INFO,RFAS -Xmx1024m" export HDFS_DATANODE_OPTS="-Dhadoop.security.logger=ERROR,RFAS -Xmx1024m"
hdfs-site.xml
<!-- NameNode有一个工作线程池,默认值是10 --> <property> <name>dfs.namenode.handler.count</name> <value>21</value> </property>
core-site.xml
<!-- 配置垃圾回收时间为60分钟 --> <property> <name>fs.trash.interval</name> <value>60</value> </property>
MapReduce调优Mapred-site.xml
<!-- 环形缓冲区大小,默认100m -->
<property>
<name>mapreduce.task.io.sort.mb</name>
<value>100</value>
</property>
<!-- 环形缓冲区溢写阈值,默认0.8 -->
<property>
<name>mapreduce.map.sort.spill.percent</name>
<value>0.80</value>
</property>
<!-- merge合并次数,默认10个 -->
<property>
<name>mapreduce.task.io.sort.factor</name>
<value>10</value>
</property>
<!-- maptask内存,默认1g; maptask堆内存大小默认和该值大小一致mapreduce.map.java.opts -->
<property>
<name>mapreduce.map.memory.mb</name>
<value>-1</value>
</property>
<!-- matask的CPU核数,默认1个 -->
<property>
<name>mapreduce.map.cpu.vcores</name>
<value>1</value>
</property>
<!-- matask异常重试次数,默认4次 -->
<property>
<name>mapreduce.map.maxattempts</name>
<value>4</value>
</property>
<!-- 每个Reduce去Map中拉取数据的并行数。默认值是5 -->
<property>
<name>mapreduce.reduce.shuffle.parallelcopies</name>
<value>5</value>
</property>
<!-- Buffer大小占Reduce可用内存的比例,默认值0.7 -->
<property>
<name>mapreduce.reduce.shuffle.input.buffer.percent</name>
<value>0.70</value>
</property>
<!-- Buffer中的数据达到多少比例开始写入磁盘,默认值0.66。 -->
<property>
<name>mapreduce.reduce.shuffle.merge.percent</name>
<value>0.66</value>
</property>
<!-- reducetask内存,默认1g;reducetask堆内存大小默认和该值大小一致mapreduce.reduce.java.opts -->
<property>
<name>mapreduce.reduce.memory.mb</name>
<value>-1</value>
</property>
<!-- reducetask的CPU核数,默认1个 -->
<property>
<name>mapreduce.reduce.cpu.vcores</name>
<value>2</value>
</property>
<!-- reducetask失败重试次数,默认4次 -->
<property>
<name>mapreduce.reduce.maxattempts</name>
<value>4</value>
</property>
<!-- 当MapTask完成的比例达到该值后才会为ReduceTask申请资源。默认是0.05 -->
<property>
<name>mapreduce.job.reduce.slowstart.completedmaps</name>
<value>0.05</value>
</property>
<!-- 如果程序在规定的默认10分钟内没有读到数据,将强制超时退出 -->
<property>
<name>mapreduce.task.timeout</name>
<value>600000</value>
</property>
Yarn调优yarn-site.xml
<!-- 选择调度器,默认容量 -->
<property>
<name>yarn.resourcemanager.scheduler.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler</value>
</property>
<!-- ResourceManager处理调度器请求的线程数量,默认50;如果提交的任务数大于50,可以增加该值,但是不能超过3台 * 4线程 = 12线程(去除其他应用程序实际不能超过8) -->
<property>
<name>yarn.resourcemanager.scheduler.client.thread-count</name>
<value>8</value>
</property>
<!-- 是否让yarn自动检测硬件进行配置,默认是false,如果该节点有很多其他应用程序,建议手动配置。如果该节点没有其他应用程序,可以采用自动 -->
<property>
<name>yarn.nodemanager.resource.detect-hardware-capabilities</name>
<value>false</value>
</property>
<!-- 是否将虚拟核数当作CPU核数,默认是false,采用物理CPU核数 -->
<property>
<name>yarn.nodemanager.resource.count-logical-processors-as-cores</name>
<value>false</value>
</property>
<!-- 虚拟核数和物理核数乘数,默认是1.0 -->
<property>
<name>yarn.nodemanager.resource.pcores-vcores-multiplier</name>
<value>1.0</value>
</property>
<!-- NodeManager使用内存数,默认8G,修改为4G内存 -->
<property>
<name>yarn.nodemanager.resource.memory-mb</name>
<value>4096</value>
</property>
<!-- nodemanager的CPU核数,不按照硬件环境自动设定时默认是8个,修改为4个 -->
<property>
<name>yarn.nodemanager.resource.cpu-vcores</name>
<value>4</value>
</property>
<!-- 容器最小内存,默认1G -->
<property>
<name>yarn.scheduler.minimum-allocation-mb</name>
<value>1024</value>
</property>
<!-- 容器最大内存,默认8G,修改为2G -->
<property>
<name>yarn.scheduler.maximum-allocation-mb</name>
<value>2048</value>
</property>
<!-- 容器最小CPU核数,默认1个 -->
<property>
<name>yarn.scheduler.minimum-allocation-vcores</name>
<value>1</value>
</property>
<!-- 容器最大CPU核数,默认4个,修改为2个 -->
<property>
<name>yarn.scheduler.maximum-allocation-vcores</name>
<value>2</value>
</property>
<!-- 虚拟内存检查,默认打开,修改为关闭 -->
<property>
<description>Whether virtual memory limits will be enforced for
containers.</description>
<name>yarn.nodemanager.vmem-check-enabled</name>
<value>false</value>
</property>
<!-- 虚拟内存和物理内存设置比例,默认2.1 -->
<property>
<name>yarn.nodemanager.vmem-pmem-ratio</name>
<value>2.1</value>
</property>