Apache Spark RDD 论文de 简单梳理
1、RDD的提出是为了解决在大规模集群中以一种容错的方式进行内存计算这个问题;
2、目前的框架对迭代式算法场景与交互数据挖掘场景的处理性能比较差(主要是对数据复用的不灵活,I/O开销大);
3、论文核心是提出一种分布式内存抽象:RDDs;是一种可以容错且并行的数据结构,可让用户将计算的中间结果保存在内存中、控制数据集的分区,实现数据存放的优化,还提供了丰富的API;
4、挑战:如何定义一个高效容错的编程接口:提供基于粗粒度转换(map、filter、join. i.e)接口,记录数据集间的转换关系,而不是真实数据(设置好依赖关系);
5、RDD抽象:一个 RDD 是一个只读,被分区的数据集。有足够的信息记录自己的依赖关系;
6、每一个RDD代表一个对象,编程者可通过对稳定存储的数据进行transformations操作,得到一个或多个RDDS;spark在定义RDDs时并没有真正计算,只有对RDDs触发actions操作才会进行计算(lazy特性);
7、RDD模型优势(与目前商用分布式对比):
Aspect(概念) | RDDs | Distribute shared memory(分布式共享内存) |
---|---|---|
Reads | 粗粒度或者细粒度 | 细粒度 |
Writes | 粗粒度 | 细粒度 |
数据一致性 | 不重要的(因为RDD是不可变的) | 取决于app 或者 runtime |
容错 | 利用lineage达到细粒度且低延迟的容错 | 需要应用checkpoints(就是需要写磁盘)并且需要程序回滚 |
计算慢的任务 | 可以利用备份的任务来解决 | 很难做到 |
计算数据的位置 | 自动的机遇数据本地性 | 取决于app(runtime是以透明为目标的) |
内存不足时的行为 | 和已经存在的数据流处理系统一样,写磁盘 | 性能大大受限 |
8、spark编程接口
开发人员需要写连接集群中的 workers 的 driver 程序来使用 spark,Driver 端程序定义了一系列的 RDDs 并且调用了 RDD 的 action 操作。Driver 的程序同时也会跟踪 RDDs 之间的的依赖关系。workers 是可以将 RDD 分区数据存储在内存中的长期存活的进程。上图中,用户写的 driver 端程序启动多个 workers,这些 workers 可以从分布式存储系统中读取数据块并且可以将计算出来的 RDD 分区数据存放在内存中。
9、RDD的相关操作(函数/java对象): transformations 是用来定义一个新的 RDD 的 lazy 操作,而actions 是真正触发一个能返回结果或者将结果写到文件系统中的计算。
10、表达RDDs:提出了基于图的 RDDs 展现方式来实现,RDDs 能跟踪很多的 transformations 操作之间依赖/血缘关系(父子关系)。如下接口:
操作接口 | 含义 |
---|---|
partitions() | 返回一个分区对象的列表 |
preferredLocations(p) | 分区p数据存储在哪些机器节点中 |
dependencies() | 返回一个依赖列表 |
iterator(p, parentIters) | 根据父亲分区的数据输入计算分区p的所有数据 |
partitioner() |
返回这个RDD是hash还是range分区的元数据信息 |
在设计这些接口的过程中将RDDs间的依赖关系定义为两种:窄依赖(一父一子【map、filter、union、join-co】)、宽依赖(一父多子从【groupByKey、join-not-co】)
11、job调度器:调度器在分配 tasks 的时候是采用延迟调度来达到数据本地性的目的(数据在哪里,计算就在哪里,实际运用中搬移计算比搬移数据成本低!)。
12、集成编译器:...
13、内存管理:Spark 在持久化 RDDs 的时候提供了 3 种存储选:存在内存中的非序列化的 java 对象、存在内存中的序列化的数据以及存储在磁盘中。
14、因为不用考虑数据的一致性,我们可以不终止程序或者 take 快照,然后在后台将 RDDs 的数据写入到存储系统中。Spark 将 RDDs 所有元素以 java 对象的形式存储在内存中,进而避免了使用Hadoop存在的耗时( In - memory HDFS(数据是在本地机器中的内存中)中读数据比从本地内存文件中读数据要多花费 2 秒钟;解析文本文件要比解析二进制文件多花费 7 秒钟;将预先解析了二进制数据转换成 java 对象也需要 3 秒钟【在论文实验环境下的数据】)。
15、可以用 RDDs 表达的模型如下:
- MapReduce:可以利用 spark 中的 flatMap 和 groupByKey 操作来表达这个模型,或者如果需要聚合的话可以使用 reduceByKey。
- DryadLINQ:DryadLINQ 系统比 MapReduce 更多的操作,但是这些操作都是直接和 RDD 的转换操作(map,groupByKey,join 等)对应的批量操作。
- SQL:和 DryadLINQ 一样,SQL 查询都是对一个数据集进行并行的操作计算。
- Pregel:Google 的 Pregel 是一个专门解决迭代图计算应用的模型,在 Pregel 中,一个程序运行一些列的相互协调的“ supersteps ”。在每一个 superstep 上,对图上的每一个顶点运行用户自定义的函数来更新这个顶点的相关的状态、改变图的拓扑结构以及向其他顶点发送下一个 superstep 需要的消息。这种模型可以表达非常多的图计算算法,包括最短路径、二部图匹配以及 PageRank。
- 迭代 MapReduce:最近提出的几个系统,包括 HaLoop 和 Twister,它们提供了可以让用户循环跑一系列的 MapReduce 任务的迭代式 MapReduce 模型。这些系统在迭代之间保持数据分区一致,Twister 也可以将数据保存在内存中。RDDs 可以很简单的表达以上两个优化,而且我们基于 spark 花了 200 行代码实现了 HaLoop。
16、性能对比实验......
原文:http://people.csail.mit.edu/matei/papers/2012/nsdi_spark.pdf