hadoop 集群调优实践总结
Posted zzjhn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hadoop 集群调优实践总结相关的知识,希望对你有一定的参考价值。
调优概述#
几乎在很多场景,MapRdeuce或者说分布式架构,都会在IO受限,硬盘或者网络读取数据遇到瓶颈.处理数据瓶颈CPU受限.大量的硬盘读写数据是海量数据分析常见情况.
IO受限例子:
CPU受限例子:
我们需要从硬件规划和软件规划等多方面结合实现性能和效率的提升。
硬件规划#
评估集群规模#
我们需要搭建多少节点的hadoop集群?回答这个问题考虑的因素比较多:预算?数据量?计算资源?
需要多少计算资源可能不是特别好评估,推荐横向扩展,随业务规模和应用发展再考虑扩展。开始可以就按照数据量来评估数据规模,估计一下每天的数据增量?保存数据的周期是多少?有没有冷数据方案?
假设每天增长的数据为600G、3备份存储,以一年规划为例,大概存储为600G3360天=633T, 再考虑增加%20的预留,考虑未来数据增长的趋势,考虑应用计算等空间需求。为节省空间可考虑压缩存储(大概可以节省70%空间)。
同时考虑一定冗余量,如果集群一部分节点不可用也要保证业务正常使用(根据集群规模评估冗余比例)。
然后结合节点硬件规划和预算,确定集群规模。假如我们需要650T存储,可以采用30台12 x 2TB的存储配置或者 60台6 x 2TB配置,但是节点数量翻翻,这样同样可以满足存储需求。需要注意的是,这种变化实际上增加了计算能力,但是,需要增加更多的电力、制冷、机架空间、网络端口密度。所以这是一种权衡,根据实际的需求考虑。
节点硬件规划#
CPU要高配还是低配?内存,存储,CPU什么配比?
一般原则:
-
CPU 选择中等频率,一般不超过两路。一般平衡价格和功耗,使充分利用CPU性能。
-
内存 考虑CPU配比和成本,保证CPU高利用率运转。48G也许是不错的选择,可以并行更多的进程,也可以增加缓存改善性能。
-
硬盘 考虑高容量的SATA硬盘(一般7200RPM),hadoop一般是存储密集型,不要求太高性能硬盘。多盘可以平衡分散IO压力,同时考虑容错,大型集群硬盘坏损是非常常见的(如果单台存储容量太高,如果节点宕机会造成内部数据复制产生抖动)。一般配置12块4T硬盘(不绝对,可以根据情况调整)。
-
网络 建议每个节点提供2 Gbps的网络吞吐量(考虑平衡成本和需求),网络拓扑不要太深,一般hadoop对横向和纵向的网络要求都比较高。
hadoop集群中各个组件对硬件需求也不同,下面根据组件特点描述硬件要求:
-
Namenode
Namenode负责协调整个集群上的数据存储,Namenode需要RAM存储集群内部数据的block原信息,一个比较靠谱的经验是,Namenode上面1GB的RAM可以支撑1 million的block信息,64GB的RAM可以支撑100 million的block信息.
硬件方面主要根据存储容量需求计算内存的需求(根据存储容量/文件数/块大小估计块数量的需求),同时考虑hdfs元数据持久的安全(硬盘一般要做raid或结合外挂存储)。CPU没有太高要求。
-
ResourceManager
负载整个集群的资源调度,不太占用资源,一般和Namenode共用即可。 -
Standby
最好和Namenode一样的配置。 -
JournalNode
资源要求不高 -
Zookeeper
资源要求不高,机器负载不要太高,一般需要3~5台 -
Datanode/NodeManger
主要的存储和计算节点,根据上述原则结合预算成本规划单机硬件。
Datanode的内存预估:
如果是I/O类型的job,每个core分配2~4GB RAM
如果是CPU类型的job,每个core分配6~8GB RAM
除了以上的job消耗内存外,整个机型还需要额外的增加:
Datanode进程管理HDFS的block,需要2GB RAM
NodeManger 进程管理节点运行的task,需要2GB RAM
OS,需要4GB RAM
下面给出一个计算公式:
推荐单件配置:
NameNode/ResourceManager/Standby类型的机器:
DataNode/TaskTrackers类型的机器:
下面是一些针对不同负载任务类型的硬件建议:
-
轻量处理型 (1U/machine): 两颗六核处理器,24-64GB内存,8块硬盘(单盘2TB or 4TB)
-
均衡型配置 (1U/machine): 两颗六核处理器,48-128GB内存,12 – 16块硬盘(单盘4TB or 6TB) ,直接和主板控制器连接。如果这种节点发生故障,将会导致集群内部数据抖动,产生大量的流量
-
存储密集型 (2U/machine): 两颗六核处理器,48-96GB内存,16-24块硬盘(单盘6TB or 8TB),如果这种节点发生故障,将会导致集群内部数据抖动,产生大量的流量
-
计算密集型(2U/machine): 两颗六核处理器,64-512GB内存,4-8块硬盘(单盘2TB or 4TB)
注:上面的CPU都是最小配置,建议使用的是 2×8,2×10,2×12 core的处理器配置(不包括超线程)。
如果新集群你还是无法预估你的最终工作量,我们建议还是使用均衡的硬件配置。
异构集群#
目前Hadoop发展为一个无所不包的数据平台,所以不仅仅是MapReudce使用,多种计算模型可插拔和Hadoop无缝结合,Hadoop2.x版本Yarn资源管理器,可以兼容多种技术模型;如:内存计算代表的saprk,impala,tez,drill,presto.磁盘计算代表的hive,mapreduce,pig. 对于一个异构集群,会同时存在多种计算模型!在硬件配置上面就需要高内存,大磁盘; Impala推荐最低配置128G内存,才能发挥优势;spark典型的CPU密集型,需要更多CPU和内存。Hive,MR磁盘计算,多磁盘读写比较频繁!当你在为集群硬件选型的时候,需要考虑的软件组件包括Apache HBase、Cloudera Impala、Presto Or Drill、Apache Phoenix和Apache spark。
可以考虑引入了Yarn的资源池,Label based scheduling基于标签的调度机制。基于标签的调度策略是hadoop yarn新引入的feature,它能让YARN更好地运行在异构集群中,进而更好地管理和调度混合类型的应用程序。
网络拓扑#
Hadoop 是IO hungry 的,既是磁盘IO hungry,也是网络IO hungry。虽然 Hadoop 在 Map 阶段调度任务时,会尽量使任务本地化,但是对于 shuffle/sort 以及 Reducer 输出来说,都会产生大量的IO。
虽然 Hadoop 不要求非要部署 10 Gb 网络,但是更高的带宽肯定会带来更好的性能。一旦你感觉需要2个以上1Gb网卡绑定以增加带宽的时候,就是考虑部署10Gb的时候了。
网络拓扑结构对 Hadoop 在某种程度上是有影响的。由于 shuffle/sort 的阶段会有大量的东西向/横向网络访问,因此网络的特点是任意节点间的带宽需求都很高。这与传统的Web服务形式的南北向/纵向带宽需要很高截然不同。如果网络拓扑设计时纵向深度很大(层级很多)就会降低网络性能。
对于 Hadoop 而言,对横向带宽需求很高。 由于这种原因,传统的树形拓扑网络就不是很适用与 Hadoop 的特性,更合适的是 spine fabric 拓扑结构。
典型部署案例#
2台 两颗8核处理器/64G内存/6块1T硬盘(os:1块,fsp_w_picpath:2块 raid1,RM:1块,zookeeper:1块 JN:1块)
1台 两颗6核处理器/24G内存/4块1T硬盘(os:1块,zookeeper:1块 JN:1块)
30台两颗10核处理器,64GB内存/12块4T硬盘
对于 Hadoop 而言,对横向带宽需求很高。 由于这种原因,传统的树形拓扑网络就不是很适用与 Hadoop 的特性,更合适的是 spine fabric 拓扑结构。
软件规划#
操作系统#
Hadoop 本身绝大多数使用的是 Java 写的,但其中也有C/C++代码。另外,由于撰写的时候,基本以Linux为设计目标系统,因此其中充斥了大量的使用 Linux 构架的思想的代码,因此一般来说会选择在 Linux 上部署。
现行系统中,RedHat Enterprise Linux, CentOS, Ubuntu Server Edition, SuSE Enterprise Linux 以及 Debian 都可以在生产环境中很好的部署 Hadoop。因此选择系统更多的是取决于你的管理工具所支持的系统、硬件支持能力、以及你们所使用的商业软件所支持的系统,还有很重要的考量是哪个系统管理人员最熟悉。
配置系统是非常消耗时间,以及容易出错的,建议采用软件配置管理系统来进行维护,而不要手动去配置。现在比较流行的是 Puppet 和 Chef。
Hadoop版本#
Apache的Hadoop版本并不是唯一的版本,有很多的公司也在专注做自己的发行版,最流行的非Apache的Hadoop发行版是Cloudera公司的Hadoop版本,也就是CDH。
-
ClouderaHadoop发行版
Cloudera是一家为Hadoop提供商业支持,专业服务和高级工具的公司。他们的CDH发行版是开源免费的。遵循Apache2.0。CDH对于用户来说没有很多的分支版本,版本号是连续的,而且有较好的兼容性,当前CDH的版本是CDH5,具有Apache2.0和1.0的特点。包括NameNode HA和Federation,同时支持MRv1和MRv2。这是当前Apache版本不具备的。CDH的另一个特点是CDH集成了不同的Hadoop生态系统项目,HDFS和MapReduce曾是Hadoop的核心组件,而在此之上出现了越来越多的组件。这些组件使得Hadoop使用起来更加友好,缩短了开发周期。使得编写MapReduce任务更加简单。
这里要提及下CDH中的Impala项目,这个项目可以完全绕过MapReduce层,直接从HDFS上获取数据,来对Hadoop进行实时的查询,CDH解决了Hadoop生态系统中众多组件的依赖。提供了大多数生态圈的组件。解决了组件之间的兼容性。这一点对用户来说选择CDH是一个很大的优势,也使得CDH变得如此受欢迎,为了辅助CDH,Cloudera发布了一个基于web的管理工具Cloudera Manager,用于规划、配置和监控Hadoop集群,Cloudera Manager拥有免费版本和付费企业版本。
-
HortonworksHadoop发行版
另外一个流行的Hadoop版本是Horonworks出品的Horonworks Data Platform(HDP),和Cloudera类似,Horonworks提供了一个一体化安装版本,并提供商业支持和服务。提供HDP1.2和2.0。其中HDP1.2提供了一些其它发行版不具备的特性,Horonworks在Hadoop1.0的基础上实现了NameNode的HA(注:这种HA利用Linux HA技术,而不是使用JournalNode),HDP包含了HCatalog,用来提供Pig和Hive这样项目的一个整合服务。为了吸引用户,Horonworks很注意和传统BI结合。HDP为Hive提供了ODBC驱动。使得可以喝大多数存在的BI工具做个适配。HDP的另外一个特点是可以运行在windows平台,不过这个稳定性还在测试中。HDP利用Ambari来做集群的管理和监控。Ambari是一个类似Cloudera Manager的Web端工具。不同的是100%完全免费和开源。 -
MapR发行版
除了Cloudera和Hortoworks外MapR也是一家提供基于Hadoop平台的公司。它们产品拥有不同的版本。M3是一个具有功能限制的免费版本,M5和M7是企业版。和Cloudera和Hortoworks不同MapR提供的软件都是不是免费的。但是提供了一些企业级的特征,MapR和Apache Hadoop的主要区别在于MapR没有使用HDFS而是使用MapR-FS文件系统。MapR-FS是用C++实现比起Java写的HDFS提供低延时和高并发度。虽然在API方面兼容,但是完全是不同的实现。除此之外,MapR-FS提供了NFS卷、集群快照和集群监控等能力,这些能力都是基于MapR-FS实现的。
选择建议:
根据团队自身情况和业务情况来决定使用哪个版本,如果团队没有hadoop定制能力,业务上也没有强烈需要,可以考虑CDH版本,相对来说会更稳定些,相关组件集成也方便,也要免费版本的CDH Manager来管理和监控集群;如果需要定制开发可以选择社区版本,这样可以方便社区交流开发,当然你也可以将CDH版本的patch更新到自己的分支,或者基于某个CDH版本开发。
Java版本#
最基本的,Hadoop 需要 JDK 方可运行。JDK 的版本是需要关注的,如果使用的是比较老的 Java 6,那么需要安装 Oracle (Sun) 的 JDK;如果是 Java 7 则可以使用系统默认的 OpenJDK 7。具体的兼容性经过了官方一些用户的测试后发布在:
http://wiki.apache.org/hadoop/HadoopJavaVersions
一般来说是选择64位系统,因为一般所配置的内存都远远大于 4GB。
参数优化#
OS参数优化#
相关参数调整,可以根据实际情况优化
-
关闭selinux,清空iptables 在服务器配置完全成功后各项服务正常后,在开启selinux
-
精简开机自启动服务
只保留crond,network,syslog,sshd服务即可,后面根据需求定制 -
调整文件描述符大小
-
删除不必要的系统用户和群组
-
同步系统时间
-
内核参数优化
-
文件系统
推荐使用ext3格式化hadoop磁盘,ext3经过大量测试(yahoo集群使用ext3),ext4和xfs都有丢数据风险。
禁用Linux逻辑管理卷(LVM)
挂载数据分区时禁用文件atime和目录atime
格式化时可以增加-m 参数减少预留空间
-
关闭THP
可以加到开机启动项中。
hadoop参数优化#
hadoop验证版本为2.6.4,其它版本酌情参考
core-site.xml
参数名 | 默认值 | 说明 |
---|---|---|
hadoop.tmp.dir | /tmp/hadoop-$user.name | hadoop中间临时文件最好单独指定目录,比如mr split信息,stag信息 |
io.file.buffer.size | 4096 | 设置IO操作缓冲区大小,较大的缓存都可以提供更高的数据传输,但这也就意味着更大的内存消耗和延迟。这个参数要设置为系统页面大小的倍数,以byte为单位,默认值是4KB,一般情况下,可以设置为64KB(65536byte) |
fs.trash.interval | 0 | 建议开启回收站功能,此参数定义.Trash目录下文件被永久删除前保留的时间 |
topology.script.file.name | -- | 集群节点比较多时,建议配置机架感知。脚本示例:rack_awareness |
hdfs-site.xml
参数名 | 默认值 | 说明 |
---|---|---|
dfs.namenode.handler.count | 10 | 服务线程个数,调大一些,一般原则是将其设置为集群大小的自然对数乘以20,即20logN,N为集群大小 |
dfs.datanode.handler.count | 10 | 服务线程个数,根据CPU核数盒实际测试决定,一般是比核数多几个 |
dfs.datanode.max.transfer.threads | 4096 | datanode所允许同时执行的发送和接受任务的数量,类似于linux上的文件句柄限制 |
dfs.namenode.name.dir | file://$hadoop.tmp.dir/dfs/name | 多个位置冗余备份,一份在本地,另外一份NFS |
dfs.datanode.data.dir | file://$hadoop.tmp.dir/dfs/data | 多个位置分布式存储,尽量多分布几个分区目录 |
dfs.datanode.failed.volumes.tolerated | 0 | 定义整个DataNode声明失败前允许多少个硬盘出现故障。任何一个本地磁盘出故障时,它的默认行为认定整个DataNode失效。可以配成硬盘数量的30% |
dfs.client.read.shortcircuit | false | 建议改为true开启短路径读 |
dfs.domain.socket.path | 设置短路径读的socket path,/var/run/hadoop-hdfs/dn._PORT 保证/var/run/hadoop-hdfs/组可写,组为root | |
dfs.blocksize | 134217728 | 新文件默认块大小,默认128M,可以根据集群规模调整,mapper数基本由输入文件的block数决定,block小引起很多小任务 |
dfs.hosts | -- | 该文件中dfs.hosts的格式是用换行符来分割主机名或者IP地址,不在列表内的主机不允许加入集群。 |
dfs.host.exclude | -- | 类似dfs.hosts,HDFS可以通过指定文件把相关节点排除在外,可以安全的卸载节点 |
dfs.datanode.balance.bandwidthPerSec | 1048576 | balancer 在DataNode之间移动数据块来保证负载均衡。如果不对平衡操作进行带宽限制,那么它会很快就会抢占所有的网络资源,影响Mapreduce作业和其它服务,太小则均衡太慢。通过此参数设置每秒最大占用带宽,这个值的单位是byte,网络带宽一般都是用bit来描述的。在设置的时候,要先计算好。 |
dfs.datanode.du.reserved | 0 | datanode会上报配置目录的空间大小总和,默认都用于dfs存储,可以预留一部分空间给别的服务,也可以减少一些无谓监控告警 |
mapred-site.xml
参数名 | 默认值 | 说明 |
---|---|---|
mapreduce.cluster.local.dir | $hadoop.tmp.dir/mapred/local | MR存储中间数据,最好多分及格目录,逗号隔开 |
mapreduce.shuffle.readahead.bytes | 4194304 | 默认为4M,ShuffleHandler在发送文件时使用posix_fadvise管理操作系统cache,可以增加预取长度提高shuffle效率 |
mapreduce.ifile.readahead.bytes | 4194304 | 默认为4M,ifile预取长度 |
mapreduce.tasktracker.outofband.heartbeat | false | 建议设成ture,在完成任务时让TaskTracker发送一个 out-of-band心跳来减少延迟 |
mapreduce.jobtracker.heartbeat.interval.min | 300 | 增加TaskTracker-to-JobTracker 心跳间隔,对小集群可以增加MR性能,可以改成1000 |
mapred.reduce.slowstart.completed.maps | 0.05 | 此属性设置当map任务完成多少的时候启动reduce任务,许多小任务可以设成0,大任务设成0.5 |
mapreduce.map.speculative | true | map任务推测执行,如果计算资源紧张,任务执行本身很耗资源情况下可以考虑设置成false。需要时通过任务参数制定 。 |
mapreduce.reduce.speculative | true | reduce任务推测执行,建议关闭,需要时通过任务参数制定 |
mapreduce.task.io.sort.mb | 100 | 以MB为单位,默认100M,根据map输出数据量的大小,可以适当的调整buffer的大小,注意是适当的调整,不是越大越好。 |
mapreduce.map.sort.spill.percent | 0.8 | buffer中达到80%时,进行spill |
mapreduce.map.output.compress | false | map输出是否压缩,建议开启减少io和网络消耗 |
mapreduce.map.output.compress.codec | org.apache.hadoop.io.compress.DefaultCodec | 建议使用snappy压缩 org.apache.hadoop.io.compress.SnappyCodec |
mapreduce.output.fileoutputformat.compress.type | RECORD | 输出SequenceFiles是的压缩类型,建议改成BLOCK |
mapreduce.map.java.opts | -- | 可以指定一些JVM参数用于调优 |
mapreduce.jobtracker.handler.count | 10 | jobtracker rpc的线程数,一般推荐为tasktracker节点数的40% |
mapreduce.tasktracker.http.threads | 40 | 获取map输出的工作线程数,可根据集群规模和硬件配置调整 |
mapreduce.tasktracker.map.tasks.maximum | 2 | tasktracker同时运行map任务数,一般可配为CPU核数或1.5倍核数 |
mapreduce.tasktracker.reduce.tasks.maximum | 2 | tasktracker同时运行reduce任务数,一般可配为CPU核数或1.5倍核数 |
mapreduce.reduce.shuffle.input.buffer.percent | 0.7 | reduce用于接受map输出buffer占堆大小的比例,类似于map端的mapreduce.task.io.sort.mb,shuffle最大使用的内存量。如果 map 输出很大而且在 reduce 到排序阶段本地磁盘 I/O 很频繁,应该尝试增加这个值。 |
mapreduce.reduce.shuffle.parallel.copies | 5 | shuffle阶段copy线程数,默认是5,一般可以设置为 4*logN N为集群大小 |
mapreduce.job.jvm.num.tasks | 1 | 默认为1,设置为 -1,重用jvm |
yarn-site.xml
参数名 | 默认值 | 说明 |
---|---|---|
yarn.scheduler.minimum-allocation-mb | 1024 | 一次申请分配内存资源的最小数量 |
yarn.scheduler.maximum-allocation-mb | 8192 | 一次申请分配内存资源的最大数量 |
yarn.nodemanager.resource.memory-mb | 8192 | 默认值为8192M,节点所在物理主机的可用物理内存总量 |
yarn.nodemanager.resource.cpu-vcores | 8 | NodeManager总的可用虚拟CPU个数,根据硬件配置设定,简单可以配置为CPU超线程个数 |
如何调优#
一般系统调优的基本步骤
在集群安装部署时应收集业务对系统的需求及特点(数据量,读写特点,计算量等),同时做好硬件的规划和初始测试(对服务器的IO/net/cpu做基本测试,保证加入集群服务器硬件没有问题)。下面主要从硬件规划和软件调优方面讨论hadoop集群的调优。
设计基准测试用例#
怎么看你的调整有效果?怎么看你是否找到了瓶颈点?要有一个对比的基线,才能比较出你的调整能改善多少性能。Hadoop提供线程测试基线应用。比如用于 HDFS I/O 测试的 TestDFSIO 和 dfsthroughput(包含在 hadoop--test.jar 中)、用于总体硬件测试的 Sort(包含在 hadoop--examples.jar 中)。可以根据自己的测试需求选择任何基准。
在所有这些基准中,当输入数据很大时,Sort 可以同时反映 MapReduce 运行时性能(在 “执行排序” 过程中)和 HDFS I/O 性能(在 “把排序结果写到 HDFS” 过程中)。另外,Sort 是 Apache 推荐的硬件基准。(http://wiki.apache.org/hadoop/Sort)
可以先测试HDFS的写入和读写性能,然后通过Sort基线测试计算和整体性能。
IO测试,会在最后输出相关统计数据
Sort基线测试
基线配置参数可以都使用默认的配置参数,然后一轮一轮修改参数,通过对比结果和服务器监控数据来做对比。
监控数据分析#
在做调优之前集群应该已经有基本的资源监控 比如 CPU、文件IO、网络IO、内存。如果没有则需要安装监控工具或监控脚步完成主机性能参数收集,常用工具(nmon/nmonanalyser,dstat等等)。
性能瓶颈的表象:资源消耗过多、外部处理系统的性能不足、资源消耗不多但程序的响应速度却仍达不到要求。
我们分析性能的主要来源数据就是主机监控数据和MR计算过程中的计数器数据等等,常见的分析点:
-
work节点的CPU资源是否有效利用,一般维持在70%左右,如果不到40%表面没有充分利用CPU
-
观察磁盘IO是否有压力,CPU wa比例是不是很大
-
观察网络流量是否正常
-
MR性能主要看shuffle阶段的计数器的表现,spill IO是否为瓶颈等
-
内存方面结合JVM优化进行调整
结合前面讲的一些优化参数点,反复测试分析结果。解决高层次性能瓶颈后再考虑应用级别的优化,比如文件格式,序列化性能,这方向调优可以使用JVM/HotSpot原生profile能力。
以上是关于hadoop 集群调优实践总结的主要内容,如果未能解决你的问题,请参考以下文章
原创 Hadoop&Spark 动手实践 8Spark 应用经验调优与动手实践