spark的内存模型_分布式存储的应用场景

spark的内存模型_分布式存储的应用场景Spark内存管理模型详解

大家好,又见面了,我是你们的朋友全栈君。

本文首发于 www.yidooo.net/2018/07/29/… 转载请注明出处

引言

Spark 作为一个基于内存的分布式计算引擎,其内存管理模块在整个系统中扮演着非常重要的角色。理解 Spark 内存管理的基本原理,有助于更好地开发 Spark 应用程序和进行性能调优。

一个Spark Application一般包括Driver和Executor两种JVM进程。Driver为主控进程,负责创建Context,提交Job,并将Job转换为Task,协调Executor间的Task执行。而Executor主要负责执行具体的计算任务,将结果返回Driver。 由于Driver的内存管理比较简单,和一般的JVM程序区别不大,所以本文重点分析Executor的内存管理。所以,本文提到的内存管理都是指Executor的内存管理。

堆内内存和堆外内存

Executor作为一个JVM进程,它的内存管理是基于JVM之上的。所以JVM的内存管理包括两种方式:

  • 堆内内存管理(On-Heap):对象分配的在JVM的堆上,对象会受GC束缚。
  • 堆外内存管理(Off-Heap):对象通过序列化分配在JVM之外的内存里,由应用程序对其进行管理,且不受GC束缚。这种内存管理方式可以避免频繁的 GC,但缺点是必须自己编写内存申请和释放的逻辑。

一般来说对象读写速度是:on-heap > off-heap > disk

内存空间分配

在Spark中,支持两种内存管理方式:静态内存管理(Static Memory Manager)和统一内存管理(Unified Memory Manager)。

Spark为Storage内存和Execution内存的管理提供了统一的接口MemoryManager,同一个 Executor内的任务都调用这个接口的方法来申请或释放内存。MemoryManager的实现上,Spark 1.6以前默认采用的是静态内存管理([StaticMemoryManager]((github.com/apache/spar…))的方式;而在Spark1.6以后,默认采用的是统一内存管理(UnifiedMemoryManager)的方式。在中Spark 1.6+中,可以通过spark.memory.useLegacyMode参数启用静态内存管理。

静态内存管理(Static Memory Manager)

静态内存管理机制下,Storage内存、Execution内存和其他内存的大小在 Spark 应用程序运行期间均为固定的,但用户可以应用程序启动前进行配置。由于这种分配已经逐渐被淘汰,但出于兼容性考虑,Spark依然保留下来。有兴趣的话,可以参考:blog.csdn.net/Lin_wj1995/…

这边主要讲下静态内存管理的弊端:静态内存管理机制实现起来较为简单,但如果用户不熟悉Spark的存储机制,或没有根据具体的数据规模和计算任务或做相应的配置,很容易造成Storage内存和Execution内存中的一方剩余大量的空间,而另一方却早早被占满,不得不淘汰或移出旧的内容以存储新的内容。

统一内存管理(Unified Memory Manager)

Spark 1.6之后引入了统一内存管理机制,该机制与静态内存管理的区别在于,Storage内存和Execution内存是共享一块内存空间的,双方可以互相占用对方的空闲区域。

堆内模型

默认情况下,Spark仅使用了堆内内存。堆内内存的大小由Spark Application启动时的–executor-memory或spark.executor.memory 参数配置。Executor内运行的并发任务共享JVM堆内内存。

Executor端的堆内内存区域大致可以分为以下四大块:

  • Storage内存(Storage Memory):主要用于存储Spark的cache数据,例如RDD的缓存、Broadcast变量,Unroll数据等。
  • Execution内存(Execution Memory):主要用于存放 Shuffle、Join、Sort、Aggregation等计算过程中的临时数据。
  • 用户内存(User Memory):主要用于存储 RDD 转换操作所需要的数据,例如 RDD 依赖等信息。
  • 预留内存(Reserved Memory):系统预留内存,会用来存储Spark内部对象。

内存分布如下图所示:

堆外模型

Spark 1.6 开始引入了Off-heap memory(SPARK-11389)。默认情况下,堆外内存是关闭的,我们可以通过spark.memory.offHeap.enabled参数启用,通过spark.memory.offHeap.size设置堆外内存大小。相比堆内内存,堆外内存的模型比较简单,只包括Storage内存和Execution内存,其分布如下图所示:

如果堆外内存被启用,那么Executor内将同时存在堆内和堆外内存,两者的使用互补影响,这个时候Executor中的Execution内存是堆内的Execution 内存和堆外的Execution内存之和,同理,Storage内存也一样。下图为Spark堆内和堆外示意图

动态占用机制

  • 在程序提交时,会根据spark.memory.storageFraction参数设置Storage内存区域和Execution内存区域。
  • 在程序运行时,如果双方的空间不不足(存储空间不足以放下一个完整的Block),则按照LRU规则存储到磁盘;如果己方空间不足而对方空间有空余,则借用对方的空间。
  • Storage占用对方内存,可将占用的部分转存到硬盘,然后”归还”借用的空间。
  • Execution占用对方内存,目前的实现是无法让对方”归还”的。因为Shuffle过程产生的文件在后面一定会被使用到,而Cache在内存的数据不一定在后面使用,归还内存可能会导致性能严重下降。

参考资料

转载于:https://juejin.im/post/5b94937e6fb9a05cd456c337

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/107325.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • MySQL中特别实用的几种SQL语句送给大家[通俗易懂]

    MySQL中特别实用的几种SQL语句送给大家[通俗易懂]在写SQL时,经常灵活运用一些SQL语句编写的技巧,可以大大简化程序逻辑。减少程序与数据库的交互次数,有利于数据库高可用性,同时也能显得你的SQL很牛B,让同事们眼前一亮。目录实用的SQL1.插入或替换2.插入或更新3.插入或忽略4.SQL中的if-else判断语句5.指定数据快照或备份6.写入查询结果集7.强制使用指定索引心得体会:高能预警,这是一篇干货满满的MySQL技术文章,总有一天,你必然会用到,记得收藏!–来自一位被技术经理毒打多年的程序员的忠.

    2022年5月1日
    42
  • 四十一、SPSS中的t检验和卡方检验[通俗易懂]

    四十一、SPSS中的t检验和卡方检验[通俗易懂]@Author:ByRunsen@Date:2020/5/14在2020年一月初,也是我大三上的寒假,我开始写书,为什么呢?因为化工原理和化工热力学挂了,我需要重拾自己的自信。对于一个大学三年,每天往死里干的人,竟然挂了两科。虽然,我化工专业已经陷入了绝境,大学我主要学习日语,Python,Java和一系列数据分析软件。所以本专栏数据分析将使用Excel,Powerbi,Python,R,Sql,SPSS,stata以及Tableau,后面还会补充BI。第五章应该是二月份完成的。文章目

    2022年5月16日
    91
  • 通过@MapperScan源码了解Spring自定义注解扫描器[通俗易懂]

    通过@MapperScan源码了解Spring自定义注解扫描器[通俗易懂]我们在使用springboot整合MyBatis时,需要在启动类上添加上@MapperScan注解,并写入mapper接口的包路径,然后我们就能通过从springIOC容器中取对应的mapper的Bean来进行持久化操作了,那么@MapperScan是如何将mapper接口实例化并注入到SpringIOC容器中的呢?首先搭建一个springboot项目,引入mybatis和mysql的相…

    2022年5月22日
    126
  • Tomcat 的安装与环境配置教程(超详细)

    Tomcat 的安装与环境配置教程(超详细)Tomcat的安装与环境配置教程目录1、下载Tomcat2、添加环境变量3、启动Tomcat4、Q&A(重要)5、后记1、下载Tomcat1>官网:ApacheTomcat®-ApacheTomcat9SoftwareDownloads这里我选择的是Tomcat9.064bitWindows(如图紫色框中所示)2>解压(记住存放目录):3>查看Tomcat的目录结构:2、添加环境变量1>右…

    2022年5月23日
    34
  • 如何查看CUDA版本和CUDNN版本

    如何查看CUDA版本和CUDNN版本cuda一般安装在/usr/local/cuda/路径下,该路径下有一个version.txt文档,里面记录了cuda的版本信息cat/usr/local/cuda/version.txt即可查询同理,cudnn的信息在其头文件里cat/usr/local/cuda/include/cudnn.h|grepCUDNN_MAJOR-A2即可查询另附我…

    2022年6月10日
    103
  • java vo 什么意思_在Java中VO , PO , BO , QO, DAO ,POJO是什么意思

    java vo 什么意思_在Java中VO , PO , BO , QO, DAO ,POJO是什么意思在Java中VO,PO,BO,DAO,POJO是什么意思最近在项目中,遇到VO,我的天。。。那就一起学习回忆一下首先简单说明下:O/RMapping是ObjectRelationalMapping(对象关系映射)的缩写。简单来说,就是将对象和关系数据库绑定,用对象来表示关系数据。JavaWEB三层架构咱们更需要熟练使用VO:值对象(ValueObject)用new关键字创建…

    2022年5月8日
    82

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号