云上大数据系列2:如何最大化利用你的集群资源
本篇是云上大数据系列第二篇文章,主要介绍
Hadoop
系统的基础调优,让Hadoop
集群的资源能够被充分利用起来。在后续的文章中,我们还将会分享更多关于云上大数据系统的性能分析和调优经验,敬请期待。
大数据系统对资源的占用较大,如果不进行合适的基础调优,很容易造成资源的浪费。尤其是在云端部署大数据系统,按量计费却没有最大化利用购买的资源,往往导致投入产出比较低。本篇我们介绍如何对Hadoop
系统进行基础优化,让 Hadoop
系统的资源能够被充分利用起来。
- 资源环境:
ecs.d1.6xlarge
× 5 - 软件系统:
CDH 5.14.2 (Spark 1.6)
- 操作系统:
CentOS 7.3
我们以 CDH 5.14.2
为例,介绍 Spark-on-YARN
的基础调优方法,在这一版本的 CDH
中,Spark
版本是 1.6
。值得注意的是,Spark 1.6
以后(含),其内存管理方式发生了变化,本文论述的方法不一定适用于之前的版本。阅读本文前,你需要有一定的 Hadoop
使用或开发经验。
1. Spark-on-YARN
的资源分配
提交 Spark
任务的时候,YARN
在做什么?
YARN
将两类主要资源(CPU
、memory
)打包为 container
,Spark
作为运行在 YARN
上的应用程序,每次使用 spark-submit
(或其他方式)提交新的任务,都会先向YARN
申请资源。简要过程可以归为:
-
ResourceManager
选择一个结点启动一个准备运行ApplicationMaster
的container
; - 如果是
cluster
模式部署,则进一步启动SparkContext
; - 接着,
ApplicationMaster
向ResourceManager
申请运行该任务所需要的资源; - 在得到资源以后通知相应的
NodeManager
启动运行Spark Executor
的container
; -
Spark Driver
为Spark Executor
分配task
,Executor
将task
的执行情况汇报给Driver
。
下文中的两幅示意图简要地展示了整个启动的流程。
如何合理地为 Spark
配置集群资源
Spark
资源的分配牵扯到 Spark
在 YARN
上的两种不同的部署模式:
-
client
模式:Spark Driver
运行在提交任务的客户端。 -
cluster
模式:Spark Driver
运行在ApplicationMaster
中;
下面就每一种模式下如何配置资源,做详细介绍:
1) client
模式:
在 client
模式下,Spark Drivr
运行在提交任务的客户端,不需要单独为其配置资源,只需要为 ApplicationMaster
和 Spark Executor
分配合适的资源即可。
为 ApplicationMaster
分配资源
client
模式下,ApplicationMaster
的作用仅限于资源的申请和分配,可以为其分配少量的资源即可,例如按照默认值,分配 1
个 vcore
和 512M
内存:
spark.yarn.am.cores=1 spark.yarn.am.memory=512m
如果我们仅配置这两项,YARN
实际申请的资源有可能比这个配置大的多,原因在于 spark.yarn.am.memory
仅限制了ApplicationMaster
(JVM进程)的堆内存空间,对于非堆内存空间,也需要做配置:
spark.yarn.am.memoryOverhead=128m
默认情况下,该值是通过下面这个公式计算得来:
spark.yarn.am.memoryOverhead=max(spark.yarn.am.memory*0.1, 384)m
此时,我们通过 ResourceManager
界面观察 YARN
的资源分配情况,有可能发现实际分配的资源比 896m (512m+384m)
还要大。这是由于 YARN
对于资源的分配存在最小粒度,总是按照最小粒度的整数倍来分配资源。
如果你用的是 Capacity Scheduler
(默认调度器),这个粒度通过下面变量来控制:
yarn.scheduler.minimum-allocation-mb
如果你用的是 Fair Scheduler
,则通过下面变量来控制:
yarn.scheduler.increment-allocation-mb
这两个变量控制了 YARN
为每个 container
分配内存空间的最小尺寸。当用户申请的内存空间小于该尺寸的时候,YARN
会按照这个最小尺寸来分配;当用户申请的内存空间大于该尺寸的时候,YARN
会按照该尺寸的整数倍来分配空间。默认值都是 1024m
。
例如,上例中,YARN
实际为 ApplicationMaster
分配的空间应该是 1024m
。
切换这两种调度器,你可以:
yarn.resourcemanager.scheduler.class=org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler
当然,YARN
为 container
分配内存也存在上线,可以通过
yarn.scheduler.maximum-allocation-mb
来控制。用户申请的内存空间超过该值,YARN
会拒绝分配并报出相应的错误。
对于 CPU
的分配,也存在同样的策略,因为比较简单,这里就不再赘述,读者对照上述关于内存的介绍,看下配置文件中相应的配置的名称便能理解。
为了便于理解,笔者画了一张示意图总结一下上述的分配策略:
为 Spark Executor
分配资源
Spark Executor
被分配到 Node Manager
结点。在每个结点上,需要为操作系统和 Hadoop
的其他进程分配一点资源。因此,总体可分配的资源比结点固有资源要少一些。Executor
的资源分配从以下几个方面来入手:
每个 Executor
分配多少 CPU
资源?
我们先来讨论这个问题,因为这决定了最终需要分配多少 Executor
。
ecs.d1.6xlarge
的每个结点有 24 Core
和 96G
内存。理论上每个 Executor
最多可以分配到 24Core
。但如上所述,我们需要为操作系统和其他进程预留一部分资源,因此实际可分配的资源少于 24Core
和 96G
内存。
Core
的数量决定了任务运行的并发度,是不是并发度越高越好呢?实验表明,HDFS
的一次读/写并发超过 5
以后,性能就会急剧下降。因此,这里推荐将每个 Executor
的 Core
数设为 5
:
spark.executor.cores=5
此时,每个结点可以起 4
个 Executor
。我们预留了 4
个 Core
给其他进程。
每个结点分配多少个 Executor
?
每个结点起 4
个 Executor
,4
个几点总共可以起 16
个 Executor
。
spark.executor.instances=16
值得注意的是, ApplicationMaster
可能被调度到任意结点,我们预留的 4
个 Core
已经足够。
每个 Executor
分配多少内存资源?
每个结点总共 96G
内存空间,我们为其他进程预留 4G
内存,剩余 92G
内存可以为 4
个 Executor
平均分配 23G
内存。考虑到 Executor
也存在非堆内存:
spark.yarn.executor.memoryOverhead=max(spark.executor.memory*0.1, 384)m
而
23 * 1024 * 0.1 > 384
因此,23G
内存中需要预留 10%
的空间给非堆内存,堆内存实际分配到的空间为:
spark.executor.memory=23*1024*0.9=21196m
此时,每个 Executor
申请的内存空间为:
21196+21196*0.1=23315.6m ~ 22.7G
我们知道 YARN
对于内存资源的分配存在最小粒度,如果此时最小粒度是 1024m
,那么实际 YARN
为每个 Executor Container
分配到的内存空间是 23G
。
值得注意的是,如果你为 Application Master
分配的内存过大,超过了预留的 4G
,那么上述的资源分配策略将会失效, YARN
会因为无法按照上述策略分配资源而报错。
另外需要注意的是,Executor
内存不宜过大,否则 Java
虚拟机对于内存的管理将存在很大的负担,往往容易造成 GC
非常严重的后果。
如果你按照上述配置来启动集群,并且成功提交了一个 Spark
任务,你大概率会发现一个问题:一个 Executor
也没起来。是哪里出问题了呢?上面我们一直在论述 Spark
资源的申请分式,却忽略了资源是由 YARN
来分配的事实。YARN
对于每个 NodeManager
的资源都设定了一个上线例如:每个 NodeManager
可以分配的最大内存是(默认 8G
):
yarn.nodemanager.resource.memory-mb
我们申请的 23G
内存远远超过了 YARN
的允许,因此无法为 Executor
分配 Container
。
同样的,对于 CPU
,YARN
也有规定:
yarn.nodemanager.resource.cpu-vcores
在实际的配置中,我们要格外注意这一点。
2) cluster
模式
在 cluster
模式下,Spark Driver
运行在 ApplicationMaster
进程中,该进程又被调度在集群的某个结点上,因此,需要通过 Spark
的相关配置来决定 ApplicationMaster
实际需要申请多少资源。ApplicationMaster
占用了集群中某个结点的资源,那么该结点上可以分配给 Spark Executor
的资源就相应的减少了,可分配的 Executor
数量也会相应的减少。
为 ApplicationMaster
分配资源
默认情况下,Spark会为Driver申请如下资源(spark-defaults.conf):
spark.driver.cores=1 spark.driver.memory=512m
现在读者已经明白了 YARN
的资源分配策略,知道实际分配的资源可能远大于上述的配置,使用
spark.yarn.driver.memoryOverhead=max(spark.driver.memory*0.1, 384)m
控制非堆内存;分配策略使用下面这张示意图可以比较清楚的表示出来:
在实际的配置中,需要注意:由于 Spark Driver
运行在 Application Master
进程中,需要适当地调高 Application Master
的内存大小。
为 Spark Executor
分配资源
Spark Executor
在 cluster
模式下的分配策略和在 client
模式下相同,这里不再赘述。需要注意的一点是:调高后的 Application Master
内存有可能超过预留的内存大小,此时,如果有必要,适当调低每个 Executor
的内存大小。
2. Spark 1.6
的内存模型
1.6
以后,Spark
采用一种叫统一内存管理模型的方式管理内存空间,如果你想要切换回静态内存分配方式,可以:
spark.memory.useLegacyMode=true
下图比较清晰得展示了统一内存管理模型下内存空间的划分:
Reserved Memory
是系统预留的空间,默认是 300M
,存储了 Spark
的一些内部对象,不能用来做数据缓存或存储计算的中间结果。在生产环境中,是不能改变的。在测试环境下可以通过下面的参数修改:
spark.testing.reservedMemory
如果为 Executor
申请的堆内存空间小于预留空间的 1.5
倍,Spark
会报错,提示你申请更大的内存空间。
User Memory
是完全由用户掌控的内存空间,默认大小为:
User_Memory_Size=(JVM_Heap_Size - Reserved_Memory_Size)*(1.0 - spark.memory.fraction)
需要注意的是,如果这块内存使用不当,是可以造成内存溢出的。Spark
不会保证这块内存的安全。
Spark Memory
顾名思义是 Spark
管理的内存空间,分为存储和计算两部分,可以通过
spark.memory.storageFraction
来改变两部分的比例。 Storage Memory
主要用来缓存从 HDFS
读取的数据或者计算的中间结果。 Execution Memory
则存储执行 task
过程中的一些对象或者 shuffle
过程中的临时数据(例如准备排序的数据)。统一内存模型以后,这两部分的内存空间可以相互借用。具体的借用方式有:
- 一方空闲,一方内存不足情况下,内存不足一方可以向空闲一方借用内存;
-
Execution Memory
可以强制拿回Storage Memory
在Execution Memory
空闲时,借用的Execution Memory
的部分内存(强制取回,而Storage Memory
数据丢失,重新计算即可); -
Storage Memory
只能等待Execution Memory
主动释放占用的StorageMemory
空闲时的内存(不强制取回,因为如果task
执行,数据丢失就会导致task
失败)。
这就意味着,当我们在配置 Storage Memory
的时候,最好不要小于其初始值大小。因为其内存空间总是会被 Execution Memory
占用而不能强制释放,这就造成如果 Storage Memory
很小,那么其实际可用的空间将更小,缓存数据的功能将被大大减弱。
希望这篇文章能对进行 Spark-on-YARN
性能调优的同学有所帮助。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
苏宁Elastic平台化实践中踩过哪些坑,又是如何解决的?
摘要:在南京 Elastic Meetup 南京交流会专场中,苏宁大数据平台搜索平台组的韩宝君为我们带来如何在大量的数据中发现数据的价值。从大数据平台的架构出发,详细解读了平台的概况和服务化平台的模块等方面的知识。最后,具体举出了在实践中出现的一些问题及对应的处理方案。数十款阿里云产品限时折扣中,赶快点击这里,领劵开始云上实践吧!直播视频回顾[PPT下载请点击]https://yq.aliyun.com/download/2885)以下为精彩视频内容整理: 苏宁大数据平台总体架构 大数据平台职责是提供苏宁集团各个业务所需要的大数据存储和计算能力,保证平台的稳定、高效运行,高平台易用性。本文将从ES平台总体介绍、ES平台化之路、实战经验这三个方面来为大家详细解读。大数据平台分为服务层、计算层、存储层三个部分。服务层包括大数据管理平台、数据云、数据开发平台、机器学习、准实时计算、OLAP、实时计算等。ES位于计算层。 Elasticsearch平台概况 集群规模包括18个集群、195个节点、接入100+个业务、4500+个索引数据量64+TB;平台功能包括独占服务和共享服务、资源利用率和业...
- 下一篇
中国HBase技术社区第二届MeetUp -笔记摘要
kylin:通过预计算(已知要查询的维度),通过spark,mr遍历计算这些指标,然后将结果存储到hbase中,最后直接查询hbase表即可。 hbase rowkey定义不宜过长,否则存储压力会很大。这里通过使用字典编码。 hbase 优化经验: 火焰图分析:从下往上分析,峰值的分布(满载还是正常) hbase内存消耗主因(memstore(写文件), blockcache(读取)) 两种不同的gc算法: hbase gc 参数配置: 使用G1算法,效果显著。 hbase WAL 和核心业务配置为ALL_SSD(所有副本使用SSD) 指定队列 分别使用HDD, ONE_SSD, ALL_SSD ,和使用读写分离。性能的变化。。 设置zone_reclaim。。可以避免本地内存不够导致OOM。(numa的问题) hbase (高一致性,一行数据一般都是通过一个regionserver来处理,通过单机来保证一致性,所以发生故障,恢复可能会较慢)和 Cassandra(HA要求高,一致性较低(一半副本写完既可以,所以读取时可能读取不到最新数据,然后通过异步刷新,知道最终写完副本), red...
相关文章
文章评论
共有0条评论来说两句吧...