Hadoop调优

lix_uan
• 阅读 1302

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.mbmapreduce.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>
点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
2年前
Hadoop2.7.3完全分布式集群安装过程
需要安装的软件Hadoop包含HDFS集群和YARN集群。部署Hadoop就是部署HDFS和YARN集群。机器数量、角色4台。NameNode1台、DataNode3台主机名IP角色amaster192.168.37.143NameNode:9000ResourceManag
Stella981 Stella981
2年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
2个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
lix_uan
lix_uan
Lv1
学无止境,即刻前行
文章
7
粉丝
5
获赞
1