Spark学习随记(1)--介绍及基本概念
Spark集批处理,实时流处理,交互式查询,机器学习与图计算于一体,避免了额多种运算场景下需要部署不同集群带来的资源浪费。
基础概念:
DAG:有向无环图(Driected Acyclic ):
大多数现有的集群计算系统都是基于非循环的数据流模型。即从稳定的物理存储(如分布式文件系统)中加载记录,记录被传入由一组确定性操作构成的DAG(Directed Acyclic Graph,有向无环图),然后写回稳定存储。DAG数据流图能够在运行时自动实现任务调度和故障恢复。
RDD就是带有分区的集合类型
特点:可以并行操作,并且是容错的
创建RDD的方法:
1)执行Transform操作(变换操作)
2)读取外部存储系统的数据集,如HDFS,HBase,或任何与Hadoop有关的数据源
RDD:弹性分布式数据集(Resilient Distributed Dataset)
基于数据流的框架并不明确支持工作集,所以需要将数据输出到磁盘,然后在每次查询时重新加载,这会带来较大的开销。针对上述问题,Spark实现了一种分布式的内存抽象,称为弹性分布式数据集(Resilient Distributed Dataset,RDD )。它支持基于工作集的应用,同时具有数据流模型的特点:自动容错、位置感知性调度和可伸缩性。RDD允许用户在执行多个查询时显式地将工作集缓存在内存中,后续的查询能够重用工作集,这极大地提升了查询速度。
案例:
val data = Array(1, 2, 3, 4, 5)
val r1 = sc.parallelize(data)
val r2 = sc.parallelize(data,2)
理解:它是一个spark提供的一个特殊的集合类。诸如普通的集合类型,如传统的Array:(1,2,3,4,5)是一个整体,但是转换成RDD后,我们可以对数据进行Partition(分区)处理,分区的目的就是为了分布式。
你可以让这个RDD有两个分区,那么有可能是这个形式:RDD(1,2) (3,4)。
这样设计的目的在于:可以进行分布式运算。
操作1:在读取时创建RDD
val distFile = sc.textFile("data.txt")
操作2:查看RDD
scala>rdd.collect
收集rdd中的数据组成Array返回,此方法将会把分布式存储的rdd中的数据集中到一台机器中组件Array
生产环境下慎用这个方法,容易内存溢出,因为spark的操作都是在内存中的。
操作3:查看RDD的分区数量
scala>rdd.partitions.size
操作4:查看RDD每个分区的元素
scala>rdd.glom.collect
此方法会将每个分区的元素以Array形式返回
与MapReduce对比
一个MR job的执行过程
- 从HDFS读取输入数据;
- 在Map阶段使用用户定于的mapper function,然后把结果Spill到磁盘
- 在Reduce阶段,从各个处于Map阶段的机器中读取Map计算的中间结果,使用用户定于的reduce function,通常最后把结果写回到HDFS
Hadoop的问题在于,一个 Hadoop job 会进行多次磁盘读写,比如写入机器本地磁盘,或是写入分布式文件系统中(这个过程包含磁盘的读写以及网络传输)。考虑到磁盘读取比内存读取慢了几个数量级,所以像 Hadoop 这样高度依赖磁盘读写的架构就一定会有性能瓶颈。
Spark的优势:
Spark 没有像 Hadoop 一样使用磁盘读写,而转用性能高得多的内存存储输入数据、处理中间结果、和存储最终结果。在大数据的场景中,很多计算都有循环往复的特点,像 Spark 这样允许在内存中缓存输入输出,上一个 job 的结果马上可以被下一个使用,性能自然要比 Hadoop MapReduce 好得多。
同样重要的是,Spark 提供了更多灵活可用的数据操作,比如 filter, join, 以及各种对 key value pair 的方便操作,甚至提供了一个通用接口,让用户根据需要开发定制的数据操作。
此外,Spark 本身作为平台也开发了 streaming 处理框架 spark streaming, SQL 处理框架 Dataframe, 机器学习库 MLlib, 和图处理库 GraphX. 如此强大,如此开放,基于 Spark 的操作,应有尽有。
问题: Hadoop 的 MapReduce 为什么不使用内存存储?
是历史原因。当初 MapReduce 选择磁盘,除了要保证数据存储安全以外,更重要的是当时企业级数据中心购买大容量内存的成本非常高,选择基于内存的架构并不现实;现在 Spark 真的赶上了好时候,企业可以轻松部署多台大内存机器,内存大到可以装载所有要处理的数据。