Spark内存都消耗在哪里了?

什么是内存消耗?

在 MapReduce 运行过程中,map task 或 reduce task 都是以JVM进程方式运行的,所以对于 MapReduce,内存消耗指的就是这些 task 进程的内存消耗。

而在 Spark 运行过程中,task 则是在 Executor JVM 中以线程的方式运行的。因此,对于 Spark 的内存消耗,在宏观上指的是 Executor JVM 的内存消耗,在微观上指的是 task 线程的内存消耗。

内存消耗的三个方面

接下来,我们从单个task线程来分析Spark内存消耗,主要有以下三个部分。

  1. Shuffle机制中产生的中间数据。 Spark 在Shuffle 过程中会使用AppendOnlyMap数据结构对数据进行聚合和排序操作,这其中涉及到的处理过程就需要消耗内存。
  2. 缓存数据。 为了避免数据重复计算,会将计算过的数据缓存到内存中,这部分会产生内存消耗。
  3. 用户代码。 如果用户在代码中自定义的数据结构和UDF也会占用一定的内存来暂存中间处理结果。
统一内存管理模型

Spark 在运行过程中,是如何对计算或者缓存的数据进行统一管理的呢?

由于内存空间有限,针对以上三个内存消耗来源,Spark 的解决方法就是将内存划分为了3个分区(分别为框架执行空间、数据缓存空间和用户代码空间),每个内存分区分别负责存储和管理以上3种内存消耗来源的一种。

但是如何平衡数据计算与缓存的内存消耗,也就是3种内存消耗分别需要多少占比的内存才是最佳的呢?

硬界限

在早期的Spark版本中,采用的是静态分配的方式。比如,数据缓存占比60%,框架执行占比20%,用户代码占比20%。但是在实际应用中,效果并不好。当有groupby()或者join()计算时,会需要比较大框架执行空间用来存放shuffle机制中的中间数据,那么框架执行分配的20%占比可能会不够用。而当用户代码空间复杂度比较高时,也会需要较大的内存空间,否则就会出现内存溢出等错误。

虽然Spark允许用户自行设置这三者的比例,但是对于用户来说,很难在应用运行时内存不断变化的过程中找到三者最优的静态比例,容易造成资源浪费或者资源不足的问题。

软界限

为了解决以上问题,最理想的方法就是为三者分配好各自内存之后,在运行过程中根据三者的实际内存需求量,进行动态调整它们的配额比例。

在Spark运行过程中,虽然用户代码的内存消耗很难被监控和估算,但是Shuffle机制中产生的中间数据和缓存数据的内存消耗却可以被监控到的。因此,可以根据监控获取到的内存需求量来动态调节后两者的内存空间。

统一内存管理模型

在 Spark 1.6版本后,便采用"静态 + 动态"的方式设计实现了更高效的统一内存管理模型。

首先将框架执行空间和数据缓存空间组合在了一起,统称为框架内存空间(Framework memory),其大小固定。并为二者设置了初始比例,在运行过程中二者的比例是可以动态调整的,以达到内存共享。同时,二者在动态调整过程中的占比也是有上下限制的,避免其中一方完全侵占另一方,进而导致后续的数据缓存操作或者Shuffle操作无法进行。

另外,在动态调整比例之后,框架执行空间还是不足,则会将Shuffle数据spill到磁盘上。而当数据缓存空间不足时,Spark会进行缓存替换、移除数据等操作。

相关推荐
snakecy10 分钟前
树莓派学习资料共享
大数据·开发语言·学习·系统架构
悠闲蜗牛�23 分钟前
技术融合新纪元:深度学习、大数据与云原生的跨界实践
大数据·深度学习·云原生
雨点保护雪花43 分钟前
15、RabbitMQ
分布式·rabbitmq
武子康1 小时前
大数据-147 Java 访问 Apache Kudu:从建表到 CRUD(含 KuduSession 刷新模式与多 Master 配置)
大数据·后端·nosql
snakecy2 小时前
信息系统项目管理师--论文case
大数据·学习·职场和发展·区块链
数据库安全3 小时前
世界互联网大会|美创科技无侵入数据安全多智体治理技术首发
大数据·人工智能·科技·数据安全
sniper-拒绝白嫖3 小时前
uniapp ios android 本地离线debug
大数据
青云交3 小时前
Java 大视界 -- 基于 Java 的大数据可视化在城市空气质量监测与污染溯源中的应用
java·spark·lstm·可视化·java 大数据·空气质量监测·污染溯源
森语林溪3 小时前
大数据环境搭建从零开始(十七):JDK 17 安装与配置完整指南
java·大数据·开发语言·centos·vmware·软件需求·虚拟机
超级无敌大好人4 小时前
mapreduce源码解读
大数据·mapreduce