引言

首先要说Spark并不是一种解决问题的框架,而是这个框架的具体实现,而论文中提出的新框架的名字叫做RDD(Resilient Distributed Datasets 弹性分布式数据集),众所周知分布式计算框架例如Map/Reduce在实际中应用如此广泛,为什么要重新设计一个新的框架呢?原因在paper中有所提到,原因就是在很多的计算场景下用户会对相同的数据集进行多次不同的查询或者其他操作,但是现有的计算框架都是把中间数据直接存放在一个可靠稳定的系统中,比如分布式文件系统,如果这部分数据存储在内存中的话无疑可以提高效率,当然既然是一个分布式环境,容错的处理也是必不可少且困难的,因为庞大的数据集很难让我们去进行数据冗余,Spark就很精彩的完成了这些事情。这篇文章主要阐述了Spark的容错,RDD实现以及相关API。

RDD

RDD的第二个D是数据集的意思,所以这其实也是一种对内存的抽象罢了,其中存储着所有的基本数据以及容错和转换所必要的元数据。

正式来说,RDD是一个只读分区记录(联想map/Reduce中map的输入)的分布式数据集,它只能基于在稳定物理存储中的数据集和其他已有的RDD上执行确定性操作来创建,基于物理存储创建就是根据分布式文件系统的某个节点上的数据创建或者直接输入数据创建,后者则依赖于RDD的特有API,我们称这类操作为 transformations ,这些操作可以把一个RDD经过某些改变转换成另一个RDD。另一类操作我们称为 action ,这类操作可以从一个RDD的数据集中导出某些值,返回给调用的程序,我们可以设定RDD的数据存储于内存中,这样就加速了这个过程

这里有一点非常重要,就是RDD的转换其实是惰性的,也就是说不是每一个transformations都会创建新的RDD,这些所有的操作都会被记录下来,等到第一次执行action的时候会把前面所有的操作组成一个AUG(有向无环图),当然这个过程由调度器执行,paper中对调度器的描述很简单,很难看出其具体实现,也希望知道的朋友可以在评论区交流心得

线方框表示RDD,实心矩形表示分区(黑色表示该分区被缓存)。要在RDD G上执行一个动作,调度器根据宽依赖创建一组stage,并在每个stage内部将具有窄依赖的转换流水线化(pipeline)。 本例不用再执行stage 1,因为B已经存在于缓存中了,所以只需要运行2和3。

从以上描述我们也可以看出,对于一个RDD来说,有一些数据是必不可缺的:

  1. RDD分区信息(分区模式和具体的存放位置)
  2. 父RDD的依赖,也就是如何可以在父节点失效时推算出父节点(容错)
  3. 记录经过哪些计算可以从父节点推算出自己

第一条是RDD本身的数据所在,后两条是为了容错。

API

我们来看看Spark的RDD中支持的操作有哪些:

transformations map(f : T ) U) : RDD[T] ) RDD[U]
filter(f : T ) Bool) : RDD[T] ) RDD[T]
flatMap(f : T )
Seq[U]) : RDD[T] ) RDD[U]
sample(fraction : Float) : RDD[T] ) RDD[T] (Deterministic sampling)
groupByKey() : RDD[(K, V)] ) RDD[(K, Seq[V])]
reduceByKey(f : (V; V) ) V) : RDD[(K, V)] ) RDD[(K, V)]
union() : (RDD[T]; RDD[T]) ) RDD[T]
join() : (RDD[(K, V)]; RDD[(K, W)]) ) RDD[(K, (V, W))]
cogroup() : (RDD[(K, V)]; RDD[(K, W)]) ) RDD[(K, (Seq[V], Seq[W]))]
crossProduct() : (RDD[T]; RDD[U]) ) RDD[(T, U)]
mapValues(f : V ) W) : RDD[(K, V)] ) RDD[(K, W)] (Preserves partitioning)
sort(c : Comparator[K]) : RDD[(K, V)] ) RDD[(K, V)]
partitionBy(p : Partitioner[K]) : RDD[(K, V)] ) RDD[(K, V)]
action count() : RDD[T] ) Long
collect() : RDD[T] ) Seq[T]
reduce(f : (T; T) ) T) : RDD[T] ) T
lookup(k : K) : RDD[(K, V)] ) Seq[V] (On hash/range partitioned RDDs)
save(path : String) : Outputs RDD to a storage system, e.g., HDFS

当然以上只是关于transformationsaction的操作,还有一些其他的操作,比如cache操作可以直接缓存RDD的数据,提高action操作和生成时用到这个RDD的RDD创建操作的效率。

还有一些RDD的内部接口:

操作 含义
partitions() 返回一组Partition对象
preferredLocations§ 根据数据存放的位置,返回分区p在哪些节点访问更快
dependencies() 返回一组依赖
iterator(p, parentIters) 按照父分区的迭代器,逐个计算分区p的元素
partitioner() 返回RDD是否hash/range分区的元数据信息(可以根据这个的返回值使得另一个RDD与其分区方式相同。这样可以提升一些transformations 操作的效率(join在分区相同时产生窄依赖))

容错

RDD的容错机制的实现是非常精彩的,但这些都基于RDD有一个粗粒度的转换接口,也就是说对于一个数据集的更新是依赖于一个相同的操作的,同时RDD是不可改变的,这样我们就可以通过记录这一系列操作来打到容错的目的,而不需要去记录所有的数据,因为这种分布式计算框架中数据是非常庞大的,如果采用冗余来容错会导致效率大幅度下降(Spark和MapReduce的容错都很巧妙)。

我们提到了RDD通过记录一系列对父RDD的操作来容错,这样我们就可以通过重新执行一遍来获取最新的数据,这里的操作可以分为两种,及窄依赖(narrow dependencies)和宽依赖(wide dependencies),如下:

  1. 窄依赖:子RDD的每个分区依赖于常数个父分区(即与数据规模无关)
  2. 宽依赖:子RDD的每个分区依赖于所有父RDD分区。例如,map产生窄依赖,而join则是宽依赖(除非父RDD被哈希分区)

显然这种区分是有意义的,首先容错时窄依赖能够更有效的恢复,因为在一个分区(分布式文件系统上的一个节点)宕机只需要重演丢失分区的父分区,二宽依赖则可能需要重演全部的父分区,因为这个丢失的分区依赖于全部的父分区;其次在真正执行transformations 时计算的过程也不一样,窄依赖允许在一个集群节点上以流水线的方式(pipeline)计算所有父分区。例如,逐个元素地执行map、然后filter操作;而宽依赖则需要首先计算好所有父分区数据。

粗粒度的转换使得我们可以使用一种简介高效的手段来实现容错,不过这也限定了Spark的编程模型,即面向批量分析应用,不适合异步细粒度的更新状态的应用

总结

对于个人认为论文很多地方都是泛泛而谈,并没有详细介绍,其实让人一头雾水,比如调度器的原理和运作方式,它到底是以一个怎样的状态在Spark中运行?driver程序的作用除了运行Worker以外还有什么用?这些也只能更深入的学习才可以理解了。学习了这篇论文以后收获就是对于容错有了更深的理解,其次对于Spark也有了一定的认识,是用一种巧妙的抽象解决了MapReduce的缺点。

其实论文看完就是知道了Spark的基础理论部分,知道它的优势,被创造的原因,实现的基本原理。距离掌握还差着十万八千里。其次至少就现在所看的文章来说RDD 本身在 Spark 生态中也渐渐变得落伍,而转向使用SparkSQL了,此方面也有几篇论文,以后从事这个方向的话会去详细了解的,现在先打好基础啦。

参考:

  1. 论文《Resilient Distributed Datasets: A Fault-Tolerant Abstraction for
    In-Memory Cluster Computing》
  2. 博文《Spark SQL 论文简述》
  3. 知乎《Spark特点及缺点?》
  4. 博文《Spark在美团的实践》
  5. 博文《Spark RDD 论文简析》

Spark RDD 论文分析相关推荐

  1. Spark RDD 论文详解(三)Spark 编程接口

    前言 本文隶属于专栏<1000个问题搞定大数据技术体系>,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和参考文献请见1000个问题搞定大数据技 ...

  2. Spark RDD 论文详解(一)摘要和介绍

    前言 本文隶属于专栏<1000个问题搞定大数据技术体系>,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和参考文献请见1000个问题搞定大数据技 ...

  3. Spark RDD 论文详解(二)RDDs

    前言 本文隶属于专栏<1000个问题搞定大数据技术体系>,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和参考文献请见1000个问题搞定大数据技 ...

  4. Spark RDD 论文详解(七)讨论

    前言 本文隶属于专栏<1000个问题搞定大数据技术体系>,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和参考文献请见1000个问题搞定大数据技 ...

  5. Spark RDD 论文详解(四)表达 RDDs

    前言 本文隶属于专栏<1000个问题搞定大数据技术体系>,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和参考文献请见1000个问题搞定大数据技 ...

  6. Spark RDD 论文详解(五)实现

    前言 本文隶属于专栏<1000个问题搞定大数据技术体系>,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和参考文献请见1000个问题搞定大数据技 ...

  7. Apache Spark RDD 论文(中文翻译)

    概要 为了能解决程序员能在大规模的集群中以一种容错的方式进行内存计算这个问题,我们提出了 RDDs 的概念.当前的很多框架对迭代式算法场景与交互性数据挖掘场景的处理性能非常差,这个是 RDDs 的提出 ...

  8. Spark基础学习笔记22:Spark RDD案例分析

    文章目录 零.本讲学习目标 一.案例分析:Spark RDD实现单词计数 (一)案例概述 (二)实现步骤 1.新建Maven管理的Spark项目 2.添加Scala和Spark依赖 3.创建WordC ...

  9. Spark 源码分析 -- RDD

    关于RDD, 详细可以参考Spark的论文, 下面看下源码 A Resilient Distributed Dataset (RDD), the basic abstraction in Spark. ...

最新文章

  1. 腾讯拥抱开源:首次公布开源路线图,技术研发向共享、复用和开源迈进
  2. UVA699 下落的树叶 The Falling Leaves(二叉树的递归遍历建树)
  3. 怎么改utf8_想重装python但有很多包怎么办?不要慌,教你如何快速重装
  4. jsp mysql demo_利用JSP+MYSQL实现注册+登入的demo----0001
  5. android表格布局的使用方法,Android布局(RelativeLayout、TableLayout等)使用方法
  6. 怎样安装php52-71,CentOS如何安装PHP5和PHP7
  7. 在vue中安装使用vux
  8. Trie 树是什么样的数据结构?有哪些应用场景?
  9. 探讨【IGE】的源代码【四】。
  10. 正阅读微信小说分销系统-功能说明与近期更新2017918
  11. 如何将照片裁剪为圆形?教你一招图片裁剪的技巧
  12. linux otl mysql_Linux下使用OTL操作mysql数据库
  13. DDD-领域驱动设计包结构
  14. 【蓝桥杯选拔赛真题54】Scratch小猫钓鱼 少儿编程scratch图形化编程 蓝桥杯选拔赛真题讲解
  15. 浙大计算机专业是不是图灵班,浙大图灵班录取条件
  16. 我,新媒体运营,却连语文都没考及格!
  17. Docker--网络详解
  18. 大专生学Java找得到工作吗_工资如何?
  19. 推荐8款插件,浏览器使用体验上升500%
  20. MATLAB 拉格朗日方程 求三自由度机械

热门文章

  1. 2019.9.2 耀中国际学校 初级汉语 班
  2. Spark Streaming处理Socket流简单实例
  3. LIN通信协议以及概念
  4. 基于单片机定时智能窗帘控制系统设计-毕业资料
  5. 无ROOT不安卓Windows11安卓子系统WSA解锁Root并包含谷歌应用商店GMS保姆级手把手安装教程含程序资源
  6. PHP的ECSHOP商城的改造成MVC添加商品功能总结
  7. 秒杀场景分析以及案例实现
  8. 鼠标滑动到物体表面提示
  9. pandas基础学习笔记(简略版)
  10. echars地图---显示到乡镇街道级别