Spark会把数据都载入到内存么?

前言

很多初学者其实对Spark的编程模式还是RDD这个概念理解不到位,就会产生一些误解。

比如,很多时候我们常常以为一个文件是会被完整读入到内存,然后做各种变换,这很可能是受两个概念的误导:

  1. RDD的定义,RDD是一个分布式的不可变数据集合
  2. Spark 是一个内存处理引擎

如果你没有主动对RDDCache/Persist,它不过是一个概念上存在的虚拟数据集,你实际上是看不到这个RDD的数据的全集的(他不会真的都放到内存里)。

RDD的本质是什么

一个RDD 本质上是一个函数,而RDD的变换不过是函数的嵌套。RDD我认为有两类:

  1. 输入RDD,典型如KafkaRDD,JdbcRDD
  2. 转换RDD,如MapPartitionsRDD

我们以下面的代码为例做分析:

sc.textFile("abc.log").map().saveAsTextFile("")
  • textFile 会构建出一个NewHadoopRDD,
  • map函数运行后会构建出一个MapPartitionsRDD
  • saveAsTextFile触发了实际流程代码的执行

所以RDD不过是对一个函数的封装,当一个函数对数据处理完成后,我们就得到一个RDD的数据集(是一个虚拟的,后续会解释)。

NewHadoopRDD是数据来源,每个parition负责获取数据,获得过程是通过iterator.next 获得一条一条记录的。假设某个时刻拿到了一条数据A,这个A会立刻被map里的函数处理得到B(完成了转换),然后开始写入到HDFS上。其他数据重复如此。所以整个过程:

  • 理论上某个MapPartitionsRDD里实际在内存里的数据等于其Partition的数目,是个非常小的数值。
  • NewHadoopRDD则会略多些,因为属于数据源,读取文件,假设读取文件的buffer是1M,那么最多也就是partitionNum*1M 数据在内存里
  • saveAsTextFile也是一样的,往HDFS写文件,需要buffer,最多数据量为 buffer* partitionNum

所以整个过程其实是流式的过程,一条数据被各个RDD所包裹的函数处理。

刚才我反复提到了嵌套函数,怎么知道它是嵌套的呢?

如果你写了这样一个代码:

sc.textFile("abc.log").map().map().........map().saveAsTextFile("")

有成千上万个map,很可能就堆栈溢出了。为啥?实际上是函数嵌套太深了。

按上面的逻辑,内存使用其实是非常小的,10G内存跑100T数据也不是难事。但是为什么Spark常常因为内存问题挂掉呢? 我们接着往下看。

Shuffle的本质是什么?

这就是为什么要分Stage了。每个Stage其实就是我上面说的那样,一套数据被N个嵌套的函数处理(也就是你的transform动作)。遇到了Shuffle,就被切开来,所谓的Shuffle,本质上是把数据按规则临时都落到磁盘上,相当于完成了一个saveAsTextFile的动作,不过是存本地磁盘。然后被切开的下一个Stage则以本地磁盘的这些数据作为数据源,重新走上面描述的流程。

我们再做一次描述:

所谓Shuffle不过是把处理流程切分,给切分的上一段(我们称为Stage M)加个存储到磁盘的Action动作,把切分的下一段(Stage M+1)数据源变成Stage M存储的磁盘文件。每个Stage都可以走我上面的描述,让每条数据都可以被N个嵌套的函数处理,最后通过用户指定的动作进行存储。

为什么Shuffle 容易导致Spark挂掉

前面我们提到,Shuffle不过是偷偷的帮你加上了个类似saveAsLocalDiskFile的动作。然而,写磁盘是一个高昂的动作。所以我们尽可能的把数据先放到内存,再批量写到文件里,还有读磁盘文件也是给费内存的动作。把数据放内存,就遇到个问题,比如10000条数据,到底会占用多少内存?这个其实很难预估的。所以一不小心,就容易导致内存溢出了。这其实也是一个很无奈的事情。

我们做Cache/Persist意味着什么?

其实就是给某个Stage加上了一个saveAsMemoryBlockFile的动作,然后下次再要数据的时候,就不用算了。这些存在内存的数据就表示了某个RDD处理后的结果。这个才是说为啥Spark是内存计算引擎的地方。在MR里,你是要放到HDFS里的,但Spark允许你把中间结果放内存里。

总结

我们从一个较新的角度解释了RDD 和Shuffle 都是一个什么样的东西。

原文链接:http://www.jianshu.com/p/b70fe63a77a8

时间: 2024-10-20 05:09:24

Spark会把数据都载入到内存么?的相关文章

Spark会把数据都载入到内存么

转载自:https://www.iteblog.com/archives/1648 前言: 很多初学者其实对于Spark的编程模式还是RDD这个概念理解不到位,就会产生一些误解.比如,很多时候我们常常以为一个文件是会被完整读入到内存,然后做各种变换,这很可能是受两个概念误导所致: 1.RDD的定义,RDD是一个分布式的不可变数据集合: 2.Spark是一个内存处理引擎: 如果你没有主动对RDD进行Cache/Persist等相关操作,它不过是一个概念上存在的虚拟机数据集, 你实际上是看不到这个R

Spark:大数据的电花火石!

什么是Spark?可能你很多年前就使用过Spark,反正当年我四六级单词都是用的星火系列,没错,星火系列的洋名就是Spark. 当然这里说的Spark指的是Apache Spark,Apache Spark?is a fast and general engine for large-scale data processing: 一种快速通用可扩展的数据分析引擎.如果想要搞清楚Spark是什么,那么我们需要知道它解决了什么问题,还有是怎么解决这些问题的. Spark解决了什么问题? 在这里不得不

Unity载入和内存管理机制

Unity几种动态载入Prefab方式的差异: 事实上存在3种载入prefab的方式: 一是静态引用,建一个public的变量,在Inspector里把prefab拉上去,用的时候instantiate 二是Resource.Load,Load以后instantiate 三是AssetBundle.Load,Load以后instantiate 三种方式有细节差异.前两种方式,引用对象texture是在instantiate时载入,而assetBundle.Load会把perfab的所有asset

[转载] Spark:大数据的“电光石火”

转载自http://www.csdn.net/article/2013-07-08/2816149 Spark已正式申请加入Apache孵化器,从灵机一闪的实验室“电火花”成长为大数据技术平台中异军突起的新锐.本文主要讲述Spark的设计思想.Spark如其名,展现了大数据不常见的“电光石火”.具体特点概括为“轻.快.灵和巧”. 轻:Spark 0.6核心代码有2万行,Hadoop 1.0为9万行,2.0为22万行.一方面,感谢Scala语言的简洁和丰富表达力:另一方面,Spark很好地利用了H

大数据实时处理-基于Spark的大数据实时处理及应用技术培训

随着互联网.移动互联网和物联网的发展,我们已经切实地迎来了一个大数据 的时代.大数据是指无法在一定时间内用常规软件工具对其内容进行抓取.管理和处理的数据集合,对大数据的分析已经成为一个非常重要且紧迫的需求.目前对大数据的分析工具,首选的是Hadoop/Yarn平台,但目前对大数据的实时分析工具,业界公认最佳为Spark.Spark是基于内存计算的大数据并行计算框架,Spark目前是Apache软件基金会旗下,顶级的开源项目,Spark提出的DAG作为MapReduce的替代方案,兼容HDFS.H

数据库数据在Java占用内存简单估算

数据库数据在Java占用内存简单估算 结论: 1.数据库记录放在JAVA里,用对象(ORM一般的处理方式)须要4倍左右的内存空间.用HashMap这样的KV保存须要10倍空间; 2.假设你主要数据是text大文本,那空间一般能够按2倍估算. 以上是一个通用数据測试结论.估大家參考. 数据库记录占用的空间大小比較好算,比方一个int占用4字节.bigint占用8字节.date占用3字节,datetime占用8字节,varchar是变长字节等.假设不想精确计算,在数据库中通过统计信息也能够比較轻松的

把项目中的那些恶心的无处存储的大块数据都丢到FastDFS之快速搭建

    在我们开发项目的时候,经常会遇到大块数据的问题(2M-100M),比如说保存报表中1w个人的ID号,他就像一个肿瘤一样,存储在服务器哪里都 觉得恶心,放在redis,mongodb中吧,一下子你就会收到报警,因为内存满了...放在mysql吧???你还得建立一个text字段,和一些小字段混在一起, 还是有点恶心,还得单独拆出来,还得怕有些sql不规范的人挺喜欢select * 的,这速度挺恶心的呀...直接放到硬盘吧,没扩展性,你1T大小的硬盘又能 怎样,照样撑爆你,放在hadoop里面

把项目中那些恶心的无处存储的大块数据都丢到FastDFS之快速搭建

原文:把项目中那些恶心的无处存储的大块数据都丢到FastDFS之快速搭建     在我们开发项目的时候,经常会遇到大块数据的问题(2M-100M),比如说保存报表中1w个人的ID号,他就像一个肿瘤一样,存储在服务器哪里都 觉得恶心,放在redis,mongodb中吧,一下子你就会收到报警,因为内存满了...放在mysql吧???你还得建立一个text字段,和一些小字段混在一起, 还是有点恶心,还得单独拆出来,还得怕有些sql不规范的人挺喜欢select * 的,这速度挺恶心的呀...直接放到硬盘

javascript数据类型(二)--- 数据、变量与内存

一.基本概念 1.1 什么是数据? 存储在内存中代表特定信息的'东东', 本质上是0101... 数据的特点: 可传递, 可运算 一切皆数据 内存中所有操作的目标: 数据 算术运算 逻辑运算 赋值 运行函数 1.2 什么是内存? 内存条通电后产生的可储存数据的空间(临时的) 内存产生和死亡: 内存条(电路版)==>通电==>产生内存空间==>存储数据==>处理数据==>断电==>内存空间和数据都消失 一块小内存的2个数据 内部存储的数据(对象类型变量保存的值是对象的地址