为了账号安全,请及时绑定邮箱和手机立即绑定

Spark 内存架构

标签:
Spark

Spark的进程都是一个JVM进程,既然是一个JVM进程,那么就可以配置它的堆大小(-Xmx和-Xms),但是进程怎么使用堆内存和为什么需要它呢?下面是一个JVM堆空间下Spark的内存分配情况

webp

Spark的内存分配

默认情况下,Spark进程的堆空间是512MB,为了安全考虑同时避免OOM,Spark只允许利用90%的堆空间,Spark中使用spark.storage.safetyFraction用来配置该值(默认是0.9)

Spark作为一个内存计算工具,可以在内存中存储数据,把内存作为他的LRU缓存(最近最少使用策略),这样大量的内存被用来缓存正在计算的数据,该部分占Safe堆的60%,Spark使用spark.storage.memoryFraction控制该值

Shuffle的内存使用情况,它通过堆大小 * spark.shuffle.safetyFraction * spark.shuffle.memoryFraction计算。 spark.shuffle.safetyFraction的默认值是0.8, spark.shuffle.memoryFraction的默认值是0.2,所以最终只能默认最多使堆空间的16%用于shuffle,通常spark会使用这块内存用于shuffle中一些别的任务,当执行shuffle时,有时对数据进行排序,当进行排序时,需要缓冲排完序后的数据(注意不能改变LRU缓冲中的数据,因为后面可能要重用),这样就需要大量的RAM存储排完序后的数据块,当没有足够的内存用于排序,可以一块一块的排序,然后最终合并。

unroll内存用于unroll,spark.storage.unrollFraction * spark.storage.memoryFraction * spark.storage.safetyFraction 。当我们需要在内存展开数据块的时候使用,那么为什么需要展开呢?因为spark允许以序列化和非序列化两种方式存储数据,序列化后的数据无法直接使用,所以使用时必须要展开。该部分内存占用缓存的内存,所以如果需要内存用于展开数据时,如果这个时候内存不够,那么Spark LRU缓存中的数据会删除一些快。


现在切换到集群模式,当你启动一个spark集群,如何看待它,下图是YARN模式下的

webp

YARN集群

当运行在YARN集群上时,YARN的ResourceMananger用来管理集群资源,集群上每个节点上的NodeManager用来管控所在节点的资源

从YARN的角度来看,每个节点看做可分配的资源池,当向ResourceManager请求资源时,它返回一些NodeManager信息,这些NodeManager将会提供execution container给你,每个execution container就是满足请求的堆大小的JVM进程,JVM进程的位置是由ResourceMananger管理的,不能自己控制,如果一个节点有64GB的内存被yarn管理(通过yarn.nodemanager.resource.memory-mb配置),当请求10个4G内存的executors时,这些executors可能运行在同一个节点上。

当在YARN上启动spark集群上
可以指定executors的数量(-num-executors或者spark.executor.instances)
可以指定每个executor使用的内存(-executor-memory或者spark.executor.memory)
可以指定每个executor使用的cpu核数(-executor-cores或者spark.executor.cores)
可以指定每个task执行使用的core数(spark.task.cpus)
可以指定driver应用使用的内存(-driver-memory和spark.driver.memory)

webp

当在集群上执行应用时,job会被切分成stages,每个stage切分成task,每个task单独调度,可以把executor的jvm进程看做task执行池,每个executor有 spark.executor.cores / spark.task.cpus execution 个执行槽,

这里有个例子:集群有12个节点运行Yarn的NodeManager,每个节点有64G内存和32的cpu核,每个节点可以启动2个executor,每个executor使用26G内存,剩下的内用系统和别的服务使用,每个executor有12个cpu核用于执行task,这样整个集群有12 machines * 2 executors per machine * 12 cores per executor / 1 core = 288 个task执行槽,这意味着spark集群可以同时跑288个task,整个集群用户缓存数据的内存有0.9 spark.storage.safetyFraction * 0.6 spark.storage.memoryFraction * 12 machines * 2 executors per machine * 26 GB per executor = 336.96 GB.



作者:Alex90
链接:https://www.jianshu.com/p/02fca6460c37


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消