目录

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

dfs.block.size

134217728

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

dfs.namenode.handler.count

40

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

dfs.datanode.max.xcievers

65536

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

dfs.balance.bandwidthPerSec

20485760

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

dfs.replication

3

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

core-site.xml

io.file.buffer.size

131072

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

fs.inmemory.size.mb

200

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

mapred-site.xml

mapred.tasktracker.map.tasks.maximum

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

mapred.tasktracker.reduce.tasks.maximum

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

mapred.max.split.size

134217728

mapred.min.split.size

134217728

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

mapred.jobtracker.heartbeat.interval.min

2000

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

mapred.jobtracker.heartbeat.scaling.factor

0.01

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

mapred.tasktracker.outofband.heartbeat

true

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

mapred.tasktracker.handler.count

40

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

mapred.tasktracker.http.threads

40

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

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

mapred.compress.map.output

true

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

mapred.job.reuse.jvm.num.tasks

-1

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

mapred.map.tasks.speculative.execuition

true

mapred.reduce.tasks.speculative.execuition

true

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

mapred.local.dir

/data0/mapred,/data1/mapred,/data2/mapred,/data3/mapred,

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

mapred.child.java.opts

-Xmx1024m

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

mapred.map.child.java.opts

-Xmx1024m

mapred.reduce.child.java.opts

-Xmx1024m

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

io.sort.mb

100

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

io.sort.spill.percent

0.8

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

mapred.reduce.parallel.copies

25

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

mapred.job.shuffle.input.buffer.percent

0.7

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

mapred.job.shuffle.merge.percent

0.66

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

mapred.reduce.slowstart.completed.maps

0.05

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

io.sort.factor

10

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

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

mapred.job.shuffle.merge.percent

0.66

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;

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

调优前:

调优后:

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

 

 

相关文章

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。