hadoop 调优

hadoop性能调优与运维

  • 硬件选择
  • 操作系统调优与JVM调优
  • hadoop参数调优
  • hive性能调优
  • hadoop运维

硬件选择

  • hadoop运行环境 
  • 如何选择合适的硬件 
     
    1. 主从节点可靠性:主节点可靠性要好于从节点
    2. 单节点选型:多路多核、高频率cpu、大内存 
      主节点: 
      NameNode的内存决定了集群保存文件数的总量。ResourceManager同时运行的作业会消耗一定的内存。 
      从节点: 
      从节点的内存需要根据cpu的虚拟核数(vcore)进行配比,cpu的vcore数计算公式为=cpu个数*单cpu核数*ht(超线程数),内存容量大小=vcore数*2GB(至少2GB)
    3. 节点数量:根据数据量确定集群规模 
      举个栗子:全量起始1TB,每天增加10G 
      一年: 
      (1TB+10GB*365)*3*1.3=17.8TB 
      节点数=18TB/2TB=9 
      总节点数=9+2=1 
      还要考虑作业并不是均匀分布,有可能会倾斜到某一个时间段,需要预留资源。
    4. 交换机选项:不要让网络I/O成为瓶颈 
      hadoop作业通常是I/O密集型而非计算密集型,瓶颈通常集中在I/O。计算能力可以通过添加节点进行线性扩展,而I/O方面的瓶颈却很难进行扩展。例如硬盘读写能力,交换机背板带宽等。30个节点以上,选择万兆交换机,价格比千兆贵3-5倍。

操作系统调优与JVM调优

操作系统调优

  1. 避免使用swap分区 
    将hadoop守护进程的数据交换到磁盘的行为可能会导致操作超时,可以通过修改linux内核参数,降低这个概率,但是不能避免
  2. 调整内存分配策略 
    操作系统内核根据vm.overcommit_memory的值来决定分配策略,并通过vm.overcommit_ratio的值来设定超过物理内存的比例,建议将vm.overcommit_memory参数设置为2,适当修改vm.overcommit_ratio参数
  3. 修改net.core.somaxconn参数 
    该参数表示socket监听backlog的上限,默认为128,建议大于等于32768,socket服务器会一次性处理backlog中的所有请求,hadoop的ipc.server.listen.queue.size参数和linux的net.core.somaxconn参数控制了监听队列的长度,需要调大
  4. 增大同时打开文件描述符的上限 
    对内核来说,所有打开的文件都通过文件描述符引用,文件描述符是一个非负整数,hadoop作业经常会读写大量文件,需要增大同时打开文件描述符的上限。
  5. 选择合适的文件系统,并禁用文件的访问时间 
    对于不同文件系统,ext3、ext4,性能会有所不同。特别的,文件的访问时间可以让用户知道哪些文件近期被查看或修改,但对于hdfs来说,获取某个文件的某个块什么时候被访问没什么意义。所以可以将其禁用。
  6. 关闭THP(Transparent Huge Pages) 
    THP是一个使用Huge Pages自动化的抽象层。它会引起cpu占用率增大,需要将其关闭。

JVM调优

有一些可以通过hadoop的参数进行设置,如堆栈大小、JVM重用、GC、flag等,将会在hadoop参数中详细介绍。

-XX:+AggressiveOpts 
-XX:+UseCompressedOops 
-XX:+UseBiasedLocking

hadoop参数调优

  • hdfs调优
  • yarn调优
  • mapreduce调优

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) 
1. 兼容各种计算框架 
2. 动态分配资源,减少资源浪费

容器内存 
yarn.nodemanager.resource.memory-mb 
最小容器内存 
yarn.scheduler.mininum-allocation-mb 
容器内存增量 
yarn.scheduler.increment-allocation-mb 
最大容器内存 
yarn.scheduler.maxinum-allocation-mb

  1. 灵活:单个容器内存和最大容器内存分配成一样,将资源分配方案交到作业提交的用户手上
  2. 严格:最小容器内存和最大容器内存分配成一样,将单个容器内存设置成固定值 
    比如你有128容器内存,最大容器内存设置100G比较合理

举个栗子: 
(4) 用户给任务设置的内存量为1000MB,为何最终分配的内存却是1024MB? 
答:为了易于管理资源和调度资源,Hadoop YARN内置了资源规整化算法,它规定了最小可申请资源量、最大可申请资源量和资源规整化因子,如果应用程序申请的资源量小于最小可申请资源量,则YARN会将其大小改为最小可申请量,也就是说,应用程序获得资源不会小于自己申请的资源,但也不一定相等;如果应用程序申请的资源量大于最大可申请资源量,则会抛出异常,无法申请成功;规整化因子是用来规整化应用程序资源的,应用程序申请的资源如果不是该因子的整数倍,则将被修改为最小的整数倍对应的值,公式为ceil(a/b)*b,其中a是应用程序申请的资源,b为规整化因子。 
以上介绍的参数需在yarn-site.xml中设置,相关参数如下: 
yarn.scheduler.minimum-allocation-mb:最小可申请内存量,默认是1024 
yarn.scheduler.minimum-allocation-vcores:最小可申请CPU数,默认是1 
yarn.scheduler.maximum-allocation-mb:最大可申请内存量,默认是8096 
yarn.scheduler.maximum-allocation-vcores:最大可申请CPU数,默认是4 
对于规整化因子,不同调度器不同,具体如下: 
FIFO和Capacity Scheduler,规整化因子等于最小可申请资源量,不可单独配置。 
Fair Scheduler:规整化因子通过参数yarn.scheduler.increment-allocation-mb和yarn.scheduler.increment-allocation-vcores设置,默认是1024和1。 
通过以上介绍可知,应用程序申请到资源量可能大于资源申请的资源量,比如YARN的最小可申请资源内存量为1024,规整因子是1024,如果一个应用程序申请1500内存,则会得到2048内存,如果规整因子是512,则得到1536内存。

容器虚拟CPU内核 
yarn.nodemanager.resource.cpu-vcores 
最小容器虚拟CPU内核数量 
yarn.scheduler.mininum-allocation-vcores 
容器虚拟CPU内核增量 
yarn.scheduler.increment-allocation-vcores 
最大容器虚拟CPU内核增量 
yarn.scheduler.maxinum-allocation-vcores

双路四核intel CPU 2*4*2=16 考虑其它应用设置为10-12比较合适

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

Hive性能调优

Join优化

小表为驱动表,或者直接将小表加载到内存,做map端join,它的关键字为/+MAPJOIN(t1)
如果想自动开启map端join,可以通过 hive.mapjoin.smalltable.filesize(默认为25000000字节)来定义小表的大小,一旦在这个范围之内,就会自动进行map端join

Reducer的数量

Hive作业Reducer数量会直接影响作业效率,Hive的Reducer的是通过如下两个参数确定: 
参数1:hive.exec.reducers.bytes.per.reducer默认为1GB 
参数2:hive.exec.reducers.max默认为999

Reducer的个数=min(参数2,总输入数据量/参数1)

列裁剪和分区裁剪

列裁剪和分区裁剪都是减少作业输入,默认开启。

hive.optimize.cp(列裁剪)、hive.optimize.pruner(分区裁剪)默认开启

SELECT col1,col2,col3 FROM table;

GROUP BY 优化

参数1:hive.map.aggr是否在Map端进行聚合,默认为true 
参数2:hive.groupby.mapagger.checkinterval在Map端进行聚合操作的条目数目,默认为100000

防止数据倾斜: 
hive.groupby.skewindata=true

示例: 
key不平均时,计算时间按key值多的reduce任务。 
 

合并小文件

当文件数目过多时,会给htfs带来压力,可以通过合并Map和Reduce的输出文件来减少文件数。

参数1:hive.merge.mapfiles=true是否合并Map阶段的输出文件 
参数2:hive.merge.mapredfiles=true是否合并Reduce阶段的输出文件 
参数3:hive.merge.size.per.task=256000000合并的文件的大小,默认为256000000

Multi-group By和Multi-insert

Multi-group By和Multi-insert是Hive特有语法,可以在同一个查询语句中使用多个不相交的insert语句,只需要扫描一遍全表。

FROM test
INSERT OVERWRITE TABLE test_by_a
SELECT a,COUNT(e) GROUP BY a/b
INSERT OVERWRITE TABLE test_by_b
SELECT b,COUNT(f) GROUP BY b
INSERT OVERWRITE TABLE test_by_c
SELECT c,COUNT(g) GROUP BY c
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

利用Union All特性

利用Union All特性将多个MapReduce作业合并

未优化的HQL:

SELECT * FROM(SELECT * FROM t1 GROUP BY c1,c2,c3
UNION ALL 
SELECT * FROM t2 GROUP BY c1,c2,c3) t3
GROUP BY c1,c2,c3
  • 1
  • 2
  • 3
  • 4

优化后的HQL:

SELECT * FROM
(SELECT * FROM t1 
UNION ALL
SELECT * FROM t2)t3 
GROUP BY c1,c2,c3
  • 1
  • 2
  • 3
  • 4
  • 5

并行执行

参数1:hive.exec.parallel=true,默认false不打开,打开会占用更多资源

全排序

ORDER BY 默认 
SORT BY

设置SORT BY方式: 

Hadoop运维

  • 基础运维
  • 集群节点动态扩容和卸载
  • 利用SecondaryNameNode恢复NameNode
  • 常见的运维技巧

基础运维

  1. 启动/停止hadoop(包括hdfs和MapReduce) 
    在HADOOP_HOME/bin下执行./start-all.sh或者./stop-all.sh
  2. 启动/停止hdfs 
    在在HADOOP_HOME/bin下执行./start-dfs.sh或者./stop-dfs.sh
  3. 启动/停止单个hdfs进程 
    在在HADOOP_HOME/bin下执行如下命令: 
    启动/停止NameNode进程 
    ./hadoop-daemon.sh start/stop namenode 
    启动/停止DataNode进程 
    ./hadoop-daemon.sh start/stop datanode

集群节点动态扩容和卸载

  1. 增加DataNode

修改slaves文件,在/hadoop/etc/hadoop目录下slaves,添加节点名称 
启动datanode:./hadoop-daemon.sh start datanode 
刷新节点:hadoop dfsadmin -redreshNodes

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

修改配置dfs.hosts和dfs.hosts.exclute,并执行hadoop dfsadmin -refreshNodes 
最后再将该节点地址去掉,再次执行:hadoop dfsadmin -refreshNodes

  1. 增加/卸载NodeManger 
    修改slaves文件,直接启动或停止

参考:hadoop2.7.1不重启,动态删除节点和新增节点

利用SecondaryNameNode恢复NameNode

  1. 确保新的NameNode${dfs.name.dir}目录存在,并移除其内容
  2. 把SecondNameNode节点中fs.checkpoint.dirNameNodefs.checkpoint.dir的所有内容复制到新的NameNode节点的{fs.checkpoint.dir}目录中。
  3. 在新NameNode上执行命令: 
    hadoop namenode -importCheckpoint 
    该步会从fs.checkpoint.dirfs.checkpoint.dir中恢复{dfs.name.dir},并启动NameNode
  4. 检查文件块完整性,执行命令:hadoop fsck /
  5. 停止NameNode
  6. 删除新NameNode ${fs.checkpoint.dir}目录下的文件
  7. 正式启动NameNode,恢复工作完成

常见的运维技巧

  1. 查看日志
  2. 清理临时文件 
    hdfs的临时文件路径:/export/hadoop/tmp/mapred/staging 
    本地临时文件路径:${mapred.local.dir}/mapred/userlogs
  3. 定期执行数据均衡脚本

你可能感兴趣的:(hadoop 调优)