hadoop性能调优与运维
- 硬件选择
- 操作系统调优与JVM调优
- hadoop参数调优
- hive性能调优
- hadoop运维
硬件选择
- hadoop运行环境
- 如何选择合适的硬件
- 主从节点可靠性:主节点可靠性要好于从节点
- 单节点选型:多路多核、高频率cpu、大内存
主节点:
NameNode的内存决定了集群保存文件数的总量。ResourceManager同时运行的作业会消耗一定的内存。
从节点:
从节点的内存需要根据cpu的虚拟核数(vcore)进行配比,cpu的vcore数计算公式为=cpu个数*单cpu核数*ht(超线程数),内存容量大小=vcore数*2GB(至少2GB) - 节点数量:根据数据量确定集群规模
举个栗子:全量起始1TB,每天增加10G
一年:
(1TB+10GB*365)*3*1.3=17.8TB
节点数=18TB/2TB=9
总节点数=9+2=1
还要考虑作业并不是均匀分布,有可能会倾斜到某一个时间段,需要预留资源。 - 交换机选项:不要让网络I/O成为瓶颈
hadoop作业通常是I/O密集型而非计算密集型,瓶颈通常集中在I/O。计算能力可以通过添加节点进行线性扩展,而I/O方面的瓶颈却很难进行扩展。例如硬盘读写能力,交换机背板带宽等。30个节点以上,选择万兆交换机,价格比千兆贵3-5倍。
操作系统调优与JVM调优
操作系统调优
- 避免使用swap分区
将hadoop守护进程的数据交换到磁盘的行为可能会导致操作超时,可以通过修改linux内核参数,降低这个概率,但是不能避免 - 调整内存分配策略
操作系统内核根据vm.overcommit_memory的值来决定分配策略,并通过vm.overcommit_ratio的值来设定超过物理内存的比例,建议将vm.overcommit_memory参数设置为2,适当修改vm.overcommit_ratio参数 - 修改net.core.somaxconn参数
该参数表示socket监听backlog的上限,默认为128,建议大于等于32768,socket服务器会一次性处理backlog中的所有请求,hadoop的ipc.server.listen.queue.size参数和linux的net.core.somaxconn参数控制了监听队列的长度,需要调大 - 增大同时打开文件描述符的上限
对内核来说,所有打开的文件都通过文件描述符引用,文件描述符是一个非负整数,hadoop作业经常会读写大量文件,需要增大同时打开文件描述符的上限。 - 选择合适的文件系统,并禁用文件的访问时间
对于不同文件系统,ext3、ext4,性能会有所不同。特别的,文件的访问时间可以让用户知道哪些文件近期被查看或修改,但对于hdfs来说,获取某个文件的某个块什么时候被访问没什么意义。所以可以将其禁用。 - 关闭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调优
- 设置合理的块大小(dfs.block.size)
- 将中间结果目录设置为分布在多个磁盘以提升写入速度(mapred.local.dir)
- 设置DadaNode处理RPC的线程数,大集群可以适当加大。(dfs.datanode.handler.count)
- 设置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
- 灵活:单个容器内存和最大容器内存分配成一样,将资源分配方案交到作业提交的用户手上
- 严格:最小容器内存和最大容器内存分配成一样,将单个容器内存设置成固定值
比如你有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
- 常见的运维技巧
基础运维
- 启动/停止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
- 确保新的NameNode${dfs.name.dir}目录存在,并移除其内容
- 把SecondNameNode节点中fs.checkpoint.dir的所有内容复制到新的NameNode节点的fs.checkpoint.dir的所有内容复制到新的NameNode节点的{fs.checkpoint.dir}目录中。
- 在新NameNode上执行命令:
hadoop namenode -importCheckpoint
该步会从fs.checkpoint.dir中恢复fs.checkpoint.dir中恢复{dfs.name.dir},并启动NameNode - 检查文件块完整性,执行命令:hadoop fsck /
- 停止NameNode
- 删除新NameNode ${fs.checkpoint.dir}目录下的文件
- 正式启动NameNode,恢复工作完成
常见的运维技巧
- 查看日志
- 清理临时文件
hdfs的临时文件路径:/export/hadoop/tmp/mapred/staging
本地临时文件路径:${mapred.local.dir}/mapred/userlogs - 定期执行数据均衡脚本