大数据内容分享(十):Hadoop 性能优化与运维

目录

Hadoop 客户端的概念

Hadoop 性能调优

hdfs调优

yarn调优

mapreduce调优

Hbase 调优

Hive 调优

Hadoop运维


Hadoop 客户端的概念

Hadoop 是主从架构,具体存储和计算由从节负责,主节点负责调度、元数据存储、资源管理。一般讲提交计算任务的工作放在主节点完成。实际上在集群中的任意一个节点都可以被用来提交任务。但是这样会增加运维难度,使得整个集群不“纯净”。

Hadoop 客户端:独立于集群之外,不参与计算和存储,只是用来提交任务。

Hadoop 客户端节点的部署:所有配置和集群中的任意节点完全相同,如此可以执行 Hadoop 的所有命令。但是在集群的配置文件 slaves 中没有配置 Hadoop 客户端的 IP 地址。所有在 Hadoop 客户端节点上不会启动集群的服务进程。这个节点部署好之后,Hadoop 客户端就接管了集群中所有与计算存储无关的任务,(例如HDFS中上传下载文件,提交计算任务等)。那么自然 Hive 和 Sqoop 等也应该安装在 Hadoop 客户端上。本质上如 Hive 之类的组件对于 Hadoop 来说都是一个客户端,通过提交任务来和集群进行交交互。一个规范的集群,用户应该通过 Hadoop 客户端来和 Hadoop 集群进行交互。

Hadoop 性能调优

Hadoop性能优化需要全方位的考虑,其本身就不是一个独立的存在,它与Jvm、操作系统甚至硬件都有着紧密的联系。因此优化工作围绕四个部分展开。

硬件

Hadoop是主从模式,因此主节点需要比从节点好一些。主要从CPU、内存和磁盘三个部分分析。

主节点

主节点上运行着NameNode,在内存方面需要有特别的考虑。因为每当HDFS启动,NameNode会将元数据加载到内存中,所以HDFS能够存储的文件总数受到NameNode内存容量的限制。(一般secondaryNameNode和不安装在主节点上,它的硬件配置应该和NameNode一样,当主节点宕机,就需要它接替)。
作业运行的元数据信息也是保存在主节点上的,因此根据集群使用场景的不同来考虑主节点的内存大小。

从节点

从节点负责计算和存储,所以要保证CPU和内存能够满足计算任务。磁盘能够满足存储数据。一般一个任务占用一个虚拟CPU(虚拟CPU的计算公式:CPU数X单个CPU核心数X单个CPU超线程数)。一般一个任务需要1G的内存。

规划磁盘是主要考虑副本的冗余情况,一般副本数为3。总的文件平摊到每一个节点,还需要至少20%~30%的磁盘空间用于存储临时文件。

计算中的中间数据的存储和网络数据的传输也是需要考虑的。因此带宽和节点的本地磁盘根据具体的任务量进行规划。

TIPS:对整个集群规模进行规划时,最常见的是根据存储空间来考虑集群大小,因为在得到存储能力的同时也得到了计算资源。

操作系统

避免使用swap分区

swap分区是指在系统物理内存不够的时候,把磁盘中的一部分空间释放,以供当前运行的程序使用。(通过vm.swappiness参数进行控制,值域是0~100,值越高说明操作系统内核越积极地将应用程序的数据交换到磁盘)。将Hadoop守护进程的数据交换到磁盘是非常危险的,有可能导致操作超时,所以应该将它设置为0。

调整内存分配策略

操作系统内核根据vm.ovecommit_memory的值来决定分配策略,其值为0、1、2。

  • 0:内核检查是否有足够的内存供进程使用,如果够,允许申请,否则申请失败,并把错误返回给进程。

  • 1:内核允许分配所以的内存,不论现在处于何种状态。

  • 2:内核允许分配超过所以物理内存和交换空间总和的内存,(通过vm.overcommit_ratio的值来设置超过的比率,50表示超过物理内存50%)。

TIPS:建议设置为2,并且调整vm.overcommit_ratio

修改net.core.somaxconn参数

net.core.somaxconn是Linux的一个内核参数,表示套接字(socket)坚挺的backlog上限。backlog是套接字的监听队列,当一个请求尚未被处理或者建立时,会进入backlog。套接字服务器可以一次处理backlog中的所有请求,处理后的请求不在位于监听队列中。(当服务器处理请求较慢时,以至于监听队列会被填满,新来的请求会被拒绝)。

在core-default.xml文件中,参数ipc.server.listen.queue.size控制了服务器套接字监听队列的长度(即backlog的长度),默认值为128。Linux的参数net.core.somaxconn的默认值同样也是128。当服务器繁忙时这个值太小了,需要增大backlog。两个参数同时增大。

TIPS:建议设置为32768

增大同时打开文件描述符的上限

对于内核而言,所以打开的文件都通过文件描述符引用。(文件描述符是一个非负整数),当打开或新建一个文件的时候,内核像进程返回一个文件描述符。读写文件时,open(),create()函数都是返回文件描述符给read()或write()函数。Hadoop作业可以同时打开多个文件,所以需要增大同时打开文件描述符的上限。

选择合适的文件系统

Hadoop主要运行在Linux上,常见的文件系统有:ext3、ext4、xfs等。当文件系统被格式化之后,还需要进行一项优化操作:禁用文件的访问时间。

TIPS:对于普通机器来书,文件访问时间可以让用户知道文件的近期查看和修改,但是对于HDFS没有意义,因为HDFS不支持修改,如果不禁用,在每次读取文件的时候还有伴随进行一次写操作,这些开销是浪费时间的,因此在挂在数据分区时,禁用文件的访问时间。

关闭THP(Transport Huge Pages)

Huge Pages就是大小我2MB~1GB的内存页,THP是一个使管理HugePages自动化的抽象层,在运行Hadoop时,THP会引起CPU占用率偏高。

JVM优化

主要调整JVM FLAGS和JVM GC,优化后效率提高4%。

Hadoop参数优化

不同版本Hadoop的参数名称可能不同。

hdfs-site.xml

<property>
<name>dfs.block.size</name>
<value>134217728</value>
</property>

TIPS:Hadoop文件块大小通常设置为128MB(根据实际测试,128MB的性能表现优于64MB、256MB和384MB)。

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

TIPS:NameNode同时和DataNode通信的线程数,默认为10,将其增大为40。

<property>
<name>dfs.datanode.max.xcievers</name>
<value>65536</value>
</property>

TIPS:dfs.datanode.max.xcievers对于DataNode来说就相当于Linux中的文件句柄的限制,当DataNode上面的连接数超过设置的值,DataNode就会拒绝连接。

<property>
<name>dfs.balance.bandwidthPerSec</name>
<value>20485760</value>
</property>

TIPS:执行start-balancecer.shd 带宽,默认我1048579(1MB/S),将其增大为20MB/S。

<property>
<name>dfs.replication</name>
<value>3</value>
</property>

TIPS:设置HDFS的文件副本数,默认为3,当许多任务同时读取一个文件时,读取可能会造成瓶颈,增大副本数可以有效缓解,但也会造成大量的磁盘空间占用,这时可以只修改Hadoop客户端的配置,从Hadoop客户端上传的文件的副本数以Hadoop客户端的设置为准。

core-site.xml

<property>
<name>io.file.buffer.size</name>
<value>131072</value>
</property>

TIPS:Hadoop的缓冲区用于Hadoop对HDFS文件的读写,还有map的中间结果输出也是在缓冲区,默认4KB,增大到128KB。

<property>
<name>fs.inmemory.size.mb</name>
<value>200</value>
</property>

TIPS:reduce阶段合并map输出的内存限制,这里设置为200,可以根据自身硬件设备进行测试。

mapred-site.xml

<property>
<name>mapred.tasktracker.map.tasks.maximum</name>
<value></value>
</property>

TIPS:Map任务的槽数(即同时运行Map任务的最大数量)根据机器配置进行设置,默认为2。

<property>
<name>mapred.tasktracker.reduce.tasks.maximum</name>
<value></value>
</property>

TIPS:Map任务的槽数(即同时运行Reduce任务的最大数量)根据机器配置进行设置,默认为2,一般要明显少于Map任务的槽数,!!每个节点所以的槽加起来的数量不能超过虚拟CPU的数量 。

<property>
<name>mapred.max.split.size</name>
<value>134217728</value>
</property>
<property>
<name>mapred.min.split.size</name>
<value>134217728</value>
</property>

TIPS:InputSplit的个数=max(mapred.min.split.size,min(mapred.max.split.size, dfs.block.size)),InputSplit的个数决定了Map任务的个数,最好使InputSplit的大小和块大小一样以实现计算本地化。

<property>
<name>mapred.jobtracker.heartbeat.interval.min</name>
<value>2000</value>
</property>

TIPS:JobTraker和TaskTracker之间的心跳间隔的最小值,默认为3000,可适当减小。

<property>
<name>mapred.jobtracker.heartbeat.scaling.factor</name>
<value>0.01</value>
</property>

TIPS:默认为0.01,表示没增加100个节点,心跳增加100 X 0.01=1秒,可以更具具体情况进行设置。

<property>
<name>mapred.tasktracker.outofband.heartbeat</name>
<value>true</value>
</property>

TIPS:是否开启带外心跳,默认为true,默认情况下tasktracker任务结束后会在下一次通知jobtracker,为了减少任务分配的延迟,开启带外心跳,在任务结束后立即通知jobtracker,以便能够马上分配任务。

<property>
<name>mapred.tasktracker.handler.count</name>
<value>40</value>
</property>

TIPS:JobTracker处理各个TaskTracker的RPC请求,该项可以根据服务器的配置和集群规模适当增加,默认为10。

<property>
<name>mapred.tasktracker.http.threads</name>
<value>40</value>
</property>

TIPS:TaskTracker用来处理Reduce任务发送的请求的HTTP服务器的线程数,可以适当增加,默认为10。

实际经验表明:只有当输入数据量很大并且容易拆分时(如文本文件),才应该启用压缩,否则会造成集群性能的降级。

<property>
<name>mapred.compress.map.output</name>
<value>true</value>
</property>

TIPS:Map任务的中间结果默认不会进行压缩,设置为true,会对中间结果进行压缩,减少数据传输时的带宽需求(mapred.map.output.compression.codec进行压缩算法的选择,有效算法需要额外安装)。

<property>
<name>mapred.job.reuse.jvm.num.tasks</name>
<value>-1</value>
</property>

TIPS:JVM重用机制,默认为1,表示一个JVM只能启动一个任务,现在设置为-1.表示1个JVM可以启动的任务数不受限制。

<property>
<name>mapred.map.tasks.speculative.execuition</name>
<value>true</value>
</property>

<property>
<name>mapred.reduce.tasks.speculative.execuition</name>
<value>true</value>
</property>

TIPS:以上两个参数分别开启Map任务和Reduce任务的推测机制,(推测机制可以有效的防止因为瓶颈而导致拖累整个作业),但是推测机制执行会抢占系统资源。

<property>
<name>mapred.local.dir</name>
<value>/data0/mapred,/data1/mapred,/data2/mapred,/data3/mapred,</value>
</property>

TIPS:设置MapReduce的中间结果的本地存储路径,将该值设置为一系列多磁盘目录有助于提高I/O效率。

<property>
<name>mapred.child.java.opts</name>
<value>-Xmx1024m</value>
</property>

TIPS:TaskTracker的Java子进程的Java参数,默认为-Xmx200m,一般来说Map任务需要的内存比Reduce任务少,该值还可以设置为TaskTracker的内存总量/槽数量。

<property>
<name>mapred.map.child.java.opts</name>
<value>-Xmx1024m</value>
</property>

<property>
<name>mapred.reduce.child.java.opts</name>
<value>-Xmx1024m</value>
</property>

TIPS:设置Map和Reduce任务进程的Java参数,可以解决mapred.map.child.java.opts粒度过粗的问题,默认为-Xmx200m。

<property>
<name>io.sort.mb</name>
<value>100</value>
</property>

TIPS:为Map任务的输出的环形缓冲区,默认100MB,可以适当增大。

<property>
<name>io.sort.spill.percent</name>
<value>0.8</value>
</property>

TIPS:为Map任务的输出的环形缓冲区的阀值,一旦缓冲区的内容占缓冲区的比例超过阀值,则将缓冲区中的内容刷写到mapred.local.dir目录中,默认为0.8,建议不低于0.5。

<property>
<name>mapred.reduce.parallel.copies</name>
<value>25</value>
</property>

TIPS:Reduce任务辅助Map任务输出的工作线程数,默认为5,可以适当调高,但不是越大越好,值过大会使得大量数据同时在网络中传输,引起I/O压力(比较科学的方式为4 X lgN,N为集群大小)。

<property>
<name>mapred.job.shuffle.input.buffer.percent</name>
<value>0.7</value>
</property>

TIPS:在shuffle的复制阶段消耗Reduce任务的内存比,默认为0.7,Reduce任务的内存为mapred.reduce.child.java.opts设置的值。

<property>
<name>mapred.job.shuffle.merge.percent</name>
<value>0.66</value>
</property>

TIPS:当内存使用率超过该值,会触发一次合并操作,将内存中的数据刷写到磁盘中,默认为0.66。

<property>
<name>mapred.reduce.slowstart.completed.maps</name>
<value>0.05</value>
</property>

TIPS:控制Reduce任务的启动时机,默认为0.05,也就是说当Map任务完成到5%,启动Reduce任务,这是为较缓慢的网络传输设计的,可以适当提高,不过Reduce任务启动时机过早或者过晚都会增加作业完成时间。

<property>
<name>io.sort.factor</name>
<value>10</value>
</property>

TIPS:控制Map端和Reduce端的合并策略,表现为一次合并的文件数目,默认为10,该值设置过大合并时消耗内存巨大,过小则合并次数过多。

除了以上配置,还可以设置任务调度器、设置跳过坏记录来提高执行效率。

<property>
<name>mapred.job.shuffle.merge.percent</name>
<value>0.66</value>
</property>

hdfs调优

  • 1.设置合理的块大小(dfs.block.size)

  • 2.将中间结果目录设置为分布在多个磁盘以提升写入速度(mapred.local.dir)

  • 3.设置DadaNode处理RPC的线程数,大集群可以适当加大。(dfs.datanode.handler.count)

  • 4.设置NameNode能同时处理请求数(dfs.namenode.handler.count)为集群规模的自然对数(lnN)的20倍。

yarn调优

yarn的资源表示模型Container,Container将资源抽象为两个维度,内存和虚拟CPU核(vcore)

  • 兼容各种计算框架

  • 动态分配资源,减少资源浪费

#容器内存 
yarn.nodemanager.resource.memory-mb

#最小容器内存  
yarn.scheduler.mininum-allocation-mb 

#容器内存增量  
yarn.scheduler.increment-allocation-mb  

#最大容器内存  
yarn.scheduler.maxinum-allocation-mb
  • 灵活:单个容器内存和最大容器内存分配成一样,将资源分配方案交到作业提交的用户手上。

  • 严格:最小容器内存和最大容器内存分配成一样,将单个容器内存设置成固定值,比如你有128容器内存,最大容器内存设置100G比较合理。

mapreduce调优

调优三原则

  • 增大作业并行程度

  • 给每个任务足够的资源

  • 在满足前两个的条件下,尽可能地给shuffle预留资源

增大作业并行程度

实质上是改变输入分片(input split)的大小,输入分片是一个逻辑概念,是一个Map Task的输入。在调优过程中,尽量让输入分片与块大小一样,这样就能实现计算本地化,减少不必要的网络传输。

计算公式为:

max(mapred.min.split.size,min(mapred.max.split.size,dfs.block.size))  
#mapred.min.split.size=1(默认值)  
#mapred.max.split.size=9223372036854775807(默认值)  
#dfs.block.size为块大小

给每个任务足够的资源

#Map任务内存
mapreduce.map.memory.mb 

#Reduce任务内存  
mapreduce.reduce.memory.mb  

#Map任务最大堆栈  
mapreduce.map.java.opts.max.heap  
#Reduce任务最大堆栈

mapred.reduce.java.opts.max.heap  
#ApplicationMaster内存

yarn.app.mapreduce.am.resource.mb

在满足前两个的条件下,尽可能地给shuffle预留资源

#最大洗牌连接  
mapreduce.shuffle.max.connections  

#I/O排序内存缓冲(MiB)  
mapreduce.task.io.sort.mb  

#I/O排序因子  
mapreduce.task.io.sort.factor  

#洗牌期间并行传输的默认数量  
mapreduce.reduce.shuffle.parallelcopies  

#压缩Map输出  
mapreduce.map.output.compress

 

Hbase 调优

Hive 调优

hive的基本运行原理:HQL——> Job——> Map/Reduce。通过以上基本原理,我们可以从以下三个方面进行调优:

  • HQL语句调优

  • job任务调优

  • map/reduce阶段调优

JOB优化

并行化执行

每个查询被Hive转化为多个阶段,有些阶段关联性不大,则可以并行化执行,减少执行时间。

set hive.exec.parallel=true;
set hive.exec.parallel.thread.number=8;

本地化执行

set hive.exec.mode.local.auto=true;

当一个join满足如下条件才能真正使用本地模式:

Job的输入数据大小必须小于参数
hive.exec.mode.local.auto.inputbytes.max(默认128MB)

Job的map数必须小于参数
hive.exec.mode.local.auto.tasks.max(默认4)

Job的reduce数必须为0或者1

job合并输入小文件

因为hive其实底层执行的是mapreduce程序,所以减少输入小文件可以提升性能。

set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat

job合并输出小文件

有点像map阶段完成后,向reduce阶段输入时使用combine,从而合并小文件向reduce输入。

set hive.merge.smallfiles.avgsize=256000000;
#当输出文件平均大小小于该值,启动新job合并文件
set hive.merge.size.per.task=64000000;
#合并之后的文件大小

hive Map端优化

#map聚合
set hive.map.aggr=true;(效果显著)

#推测执行
mapred.map.tasks.speculative.execution

#Map端的shuffle优化
io.sort.mb
io.sort.spill.percent
min.num.spill.for.combine
io.sort.factor
io.sort.record.percent

#reduce端的shuffle优化。
mapred.reduce.parallel.copies
mapred.reduce.copy.backoff
io.sort.factor
mapred.job.shuffle.input.buffer.percent
mapred.job.reduce.input.buffer.percent

当然,还有其他优化方式,例如Fetch抓取。

  • 理论分析

Fetch抓取是指,Hive中对某些情况的查询可以不必使用MapReduce计算。例如:SELECT * FROM employees;在这种情况下,Hive可以简单地读取employee对应的存储目录下的文件,然后输出查询结果到控制台。

hive-default.xml.template文件中hive.fetch.task.conversion默认是more,老版本hive默认是minimal,该属性修改为more以后,在全局查找、字段查找、limit查找等都不走mapreduce。

可以在配置文件中进行配置,也可以进行set设置。

#把hive.fetch.task.conversion设置成none,然后执行查询语句,都会执行mapreduce程序。
hive (default)> set hive.fetch.task.conversion=none;
hive (default)> select * from emp;
hive (default)> select ename from emp;
hive (default)> select ename from emp limit 3;

#把hive.fetch.task.conversion设置成more,然后执行查询语句,如下查询方式都不会执行mapreduce程序。
hive (default)> set hive.fetch.task.conversion=more;
hive (default)> select * from emp;
hive (default)> select ename from emp;
hive (default)> select ename from emp limit 3;

以下附上两张图(调优前后对比)

调优前:


ac74d1c9f22c4339b464375b21730111.png

调优后:

79cfa52ea0b04df1b5b0b06cfcca16db.png

Hadoop运维

  • 基础运维

  • 集群节点动态扩容和卸载

  • 利用SecondaryNameNode恢复NameNode

  • 常见的运维技巧

基础运维

启动/停止hadoop(包括hdfs和MapReduce)

在HADOOP_HOME/bin下执行./start-all.sh或者./stop-all.sh

启动/停止hdfs

在在HADOOP_HOME/bin下执行./start-dfs.sh或者./stop-dfs.sh

启动/停止单个hdfs进程

在在HADOOP_HOME/bin下执行如下命令:  
#启动/停止NameNode进程  
./hadoop-daemon.sh start/stop namenode

#启动/停止DataNode进程  
./hadoop-daemon.sh start/stop datanode

集群节点动态扩容和卸载

增加DataNode

修改slaves文件,在/hadoop/etc/hadoop目录下slaves,添加节点名称

  • 启动datanode:./hadoop-daemon.sh start datanode

  • 刷新节点:hadoop dfsadmin -redreshNodes

  • 卸载DataNode

stop datanode命令只能停止DataNode,并不能将数据完全转移。

修改配置dfs.hosts和dfs.hosts.exclute,并执行hadoop dfsadmin -refreshNodes

最后再将该节点地址去掉,再次执行:hadoop dfsadmin -refreshNodes

  • 增加/卸载NodeManger

修改slaves文件,直接启动或停止

利用SecondaryNameNode恢复NameNode

1.确保新的NameNode${dfs.name.dir}目录存在,并移除其内容。

2.把SecondNameNode节点中fs.checkpoint.dir的所有内容复制到新的NameNode节点的fs.checkpoint.dir的所有内容复制到新的NameNode节点的{fs.checkpoint.dir}的所有内容复制到新的NameNode节点的{fs.checkpoint.dir}目录中。

3.在新NameNode上执行命令:

hadoop namenode -importCheckpoint  
#该步会从fs.checkpoint.dir中恢复fs.checkpoint.dir中恢复{fs.checkpoint.dir}中恢复{dfs.name.dir},并启动NameNode
  • 4.检查文件块完整性,执行命令:hadoop fsck /

  • 5.停止NameNode

  • 6.删除新NameNode ${fs.checkpoint.dir}目录下的文件

  • 7.正式启动NameNode,恢复工作完成

常见的运维技巧

查看日志

NameNode 当天日志路径:$HADOOP_HOME/logs/hadoop-hadoop-namenode-master.log
ResourceManager 当天日志路径:$HADOOP_HOME/logs/hadoop-hadoop-resourcemanager-master.log
DataNode 当天日志路径:$HADOOP_HOME/logs/hadoop-hadoop-datanode-slave1.log
NodeManager 当天日志路径:$HADOOP_HOME/logs/hadoop-hadoop-nodemanager-slave1.log

清理临时文件

很多时候,集群的频繁操作,会产生大量的临时日志,会使得这些文件十分巨大,影响正常的HDFS存储,可以根据实际情况进行清理操作。

hdfs的临时文件路径:/export/hadoop/tmp/mapred/staging  
本地临时文件路径:${mapred.local.dir}/mapred/userlogs

定期执行数据均衡脚本

导致HDFS数据不均衡的原因有很多种,比如:新增一个DataNode、快速删除HDFS上的大量文件、计算任务分布不均衡等。

当我感觉到数据不均衡时,就可以使用Hadoop自带的均衡脚本来重新平衡整个集群,脚本的路径如下:

$HADOOP_HOME/bin/start-balancer.sh

 

 

  • 24
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

之乎者也·

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值