要学习分布式以及数据分析、机器学习之类的,觉得可以通过一些实际的编码项目入手。最近Spark很火,也有不少招聘需要Spark,而且与传统的Hadoop相比,Spark貌似有一些优势。所以就以Spark来学习下。

安装部署等可以参考之前的文章:http://www.cnblogs.com/charlesblc/p/6014158.html

貌似主从Spark都部署在了 m42n05 机器上。看后续是否需要增加其他slave。

首先看了知乎这篇文章,了解了一些基础(link

在2010年开源,目前是Apache软件基金会的顶级项目。随着Spark在大数据计算领域的暂露头角,越来越多的企业开始关注和使用。

2014年11月,Spark在Daytona Gray Sort 100TB Benchmark竞赛中打破了由Hadoop MapReduce保持的排序记录。Spark利用1/10的节点数,把100TB数据的排序时间从72分钟提高到了23分钟。

Spark在架构上包括内核部分和4个官方子模块

Spark SQL

Spark Streaming

机器学习库MLlib

图计算库GraphX

由Spark在伯克利的数据分析软件栈BDAS(Berkeley Data Analytics Stack)中的位置可见,Spark专注于数据的计算,而数据的存储在生产环境中往往还是由Hadoop分布式文件系统HDFS承担。

这里要先说一下BDAS,是伯克利大学的AMPLab打造的用于大数据的分析的一套开源软件栈,这其中包括了这两年火的爆棚的Spark,也包括了冉冉升起的分布式内存系统Alluxio(Tachyon),当然还包括著名的资源管理的开源软件Mesos。可以说Amplab最近几年引领了大数据发展的技术创新的浪潮。

从它的官网(https://amplab.cs.berkeley.edu/software/),可以看到这张图片:

其中,有不少文字是有链接,指向各自项目的主页的。要查看这些链接,可以到上面BDAS的官网。

参考这篇文章(http://www.oschina.net/question/2360202_2163562)给了BDAS的介绍:

在这整个技术栈中,最下层是资源管理层,也是广大大数据技术从业者都了解的两个技术:Amplab主导开发的Mesos和Hadoop社区的Yarn,二者各有其优缺点,笔者在去年的微信公众号也做过一些介绍,这里不详细赘述。

在资源管理层上边,则是存储层,包括了HDFS,S3,Ceph等技术,也都广为所知,Amplab在BDAS上也都是用这些广为所知的分布式文件系统来解决存储问题。但是基于分布式文件系统,Amblab则做了分布式内存系统Alluxio(以前叫做Tachyon)。关于Alluxio,国内的大数据技术从业者都已经有了不错的了解,百度用Alluxio取得了非常不错的性能的提升,TalkingData也在进行测试,期望不久的将来能够在我们的技术栈中使用上。

Succinct对于很多人可能比较陌生,它是Amplab对于压缩的数据进行高效检索的一套开源的解决方案,基本的出发点是用压缩的后缀树(compressed suffix array)来存储数据来达到高效的压缩存储和检索效率,具体的技术细节,笔者后边会单独写一篇文章介绍。

处理引擎就是Spark core了,这个不用我做更多的介绍了,国内关于Spark的文章已经多不胜数,关于RDD的技术原理基本上是面试必备了。

访问和接口层中,Spark SQL则是Spark社区这两年的重点,相关的技术资料也很多,包括DataFrame,DataSet的相关概念也逐渐的深入人心了。Spark Streaming一直有人诟病,从近期Spark的一些资料介绍看,Spark 2.0将会在Spark Streaming上有大的改进,让我们拭目以待Spark 2.0的发布吧。

BlinkDB我去年就在关注,它的出发点是用采样方式做大数据的处理,不过似乎并不活跃,在alpha 0.2.0版本都已经两年了都没有变化。

SampleClean配合Ampcrowd是进行数据清洗的开源套件,这和我们TalkingDat正在做的大禹系统有点类似,后边我也会单独进行介绍。

SparkR不用我过多介绍,是支持在Spark上运行R。GraphX则是在Spark上的图算法包,未来我相信会有越来越多的人会关注图的算法。

Splash是在Spark上的一个对随机学习算法进行并行的一个并行计算框架,支持SGD,SDCA等等。

Velox是Amplab正在开发的支持实时个性化预测的一套模型系统,在这个keynote中,Michael Franklin对Velox做了重点的介绍,可见它非常受到Amplab的重视,从源代码的描述看,它支持实时个性化预测,与Spark和KeystoneML做了集成,并且支持离线batch和在线的模型训练。具体的细节,笔者后边会专门进行专题的介绍。

KeystoneML是AmpLab为了简化构造机器学习流水线而开发的一套系统,仍旧在开发过程中。通过KeystoneML,可以方便的定义机器学习算法的pipeline,并且方便的在Spark上进行并行化处理。后边我也会单独进行KeysoneML的介绍。
MLLib不需要过多的赘述,是Spark上的机器学习算法库,很多公司已经在用MLLib在Spark上进行各种机器学习算法的实践了。
 
回到知乎(link)的内容(后来发现,内容来自http://www.open-open.com/lib/view/open1422579658533.html):
 
Spark被设计成支持多场景的通用大数据计算平台,它可以解决大数据计算中的批处理,交互查询及流式计算等核心问题。Spark可以从多数据源的读取数据,并且拥有不断发展的机器学习库和图计算库供开发者使用。数据和计算在Spark内核及Spark的子模块中是打通的,这就意味着Spark内核和子模块之间成为一个整体。Spark的各个子模块以Spark内核为基础,进一步支持更多的计算场景,例如使用Spark SQL读入的数据可以作为机器学习库MLlib的输入。以下列举了一些在Spark平台上的计算场景。
 

之前在大数据概述的课程中我们提到了Hadoop,大数据工程师都非常了解Hadoop MapReduce一个最大的问题是在很多应用场景中速度非常慢,
只适合离线的计算任务。这是由于MapReduce需要将任务划分成map和reduce两个阶段,map阶段产生的中间结果要写回磁盘,
而在这两个阶段之间需要进行shuffle操作。Shuffle操作需要从网络中的各个节点进行数据拷贝,使其往往成为最为耗时的步骤,
这也是Hadoop MapReduce慢的根本原因之一,大量的时间耗费在网络磁盘IO中而不是用于计算。
在一些特定的计算场景中,例如像逻辑回归这样的迭代式的计算,MapReduce的弊端会显得更加明显。
那Spark是如果设计分布式计算的呢?首先我们需要理解Spark中最重要的概念--弹性分布数据集(Resilient Distributed Dataset),也就是RDD。

弹性分布数据集RDD

RDD是Spark中对数据和计算的抽象,是Spark中最核心的概念,它表示已被分片(partition),不可变的并能够被并行操作的数据集合。
对RDD的操作分为两种transformation和action。
Transformation操作是通过转换从一个或多个RDD生成新的RDD。
Action操作是从RDD生成最后的计算结果。在Spark最新的版本中,提供丰富的transformation和action操作,
比起MapReduce计算模型中仅有的两种操作,会大大简化程序开发的难度。
RDD的生成方式只有两种,一是从数据源读入,另一种就是从其它RDD通过transformation操作转换。
一个典型的Spark程序就是通过Spark上下文环境(SparkContext)生成一个或多个RDD,
在这些RDD上通过一系列的transformation操作生成最终的RDD,最后通过调用最终RDD的action方法输出结果。

每个RDD都可以用下面5个特性来表示,其中后两个为可选的:

分片列表(数据块列表)
计算每个分片的函数
对父RDD的依赖列表
对key-value类型的RDD的分片器(Partitioner)(可选)
每个数据分片的预定义地址列表(如HDFS上的数据块的地址)(可选)

虽然Spark是基于内存的计算,但RDD不光可以存储在内存中

根据useDisk、useMemory、useOffHeap, deserialized、replication五个参数的组合Spark提供了12种存储级别,
在后面介绍RDD的容错机制时,我们会进一步理解。值得注意的是当StorageLevel设置成OFF_HEAP时,RDD实际被保存到Tachyon中。
Tachyon是一个基于内存的分布式文件系统,目前正在快速发展,在这里我们就不做详细介绍啦,可以通过其官方网站进一步了解。

DAG、Stage与任务的生成

Spark的计算发生在RDD的action操作,而对action之前的所有transformation,Spark只是记录下RDD生成的轨迹,而不会触发真正的计算。

Spark内核会在需要计算发生的时刻绘制一张关于计算路径的有向无环图,也就是DAG。举个例子,在图2中,从输入中逻辑上生成A和C两个RDD,
经过一系列transformation操作,逻辑上生成了F,注意,我们说的是逻辑上,因为这时候计算没有发生,Spark内核做的事情只是记录了RDD的生成和依赖关系。
当F要进行输出时,也就是F进行了action操作,Spark会根据RDD的依赖生成DAG,并从起点开始真正的计算。

有了计算的DAG图,Spark内核下一步的任务就是根据DAG图将计算划分成任务集,也就是Stage,这样可以将任务提交到计算节点进行真正的计算。

Spark计算的中间结果默认是保存在内存中的,Spark在划分Stage的时候会充分考虑在分布式计算中可流水线计算(pipeline)的部分来提高计算的效率,而在这个过程中,主要的根据就是RDD的依赖类型。

根据不同的transformation操作,RDD的依赖可以分为窄依赖(Narrow Dependency)和宽依赖(Wide Dependency,在代码中为ShuffleDependency)两种类型。

窄依赖指的是生成的RDD中每个partition只依赖于父RDD(s) 固定的partition。宽依赖指的是生成的RDD的每一个partition都依赖于父 RDD(s) 所有partition。窄依赖典型的操作有map, filter, union等,宽依赖典型的操作有groupByKey, sortByKey等。

可以看到,宽依赖往往意味着shuffle操作,这也是Spark划分stage的主要边界。对于窄依赖,Spark会将其尽量划分在同一个stage中,因为它们可以进行流水线计算。

我们再通过下图详细解释一下Spark中的Stage划分。

我们从HDFS中读入数据生成3个不同的RDD,通过一系列transformation操作后再将计算结果保存回HDFS。

可以看到这幅DAG中只有join操作是一个宽依赖,Spark内核会以此为边界将其前后划分成不同的Stage.

同时我们可以注意到,在图中Stage2中,从map到union都是窄依赖,这两步操作可以形成一个流水线操作,通过map操作生成的partition可以不用等待整个RDD计算结束,而是继续进行union操作,这样大大提高了计算的效率。

图:Spark中的Stage划分

Spark在运行时会把Stage包装成任务提交,有父Stage的Spark会先提交父Stage。弄清楚了Spark划分计算的原理,我们再结合源码看一看这其中的过程。下面的代码是DAGScheduler中的得到一个RDD父Stage的函数,可以看到宽依赖为划分Stage的边界。

/**
* Get or create the list of parent stages for a given RDD. The stages will be assigned the
* provided jobId if they haven't already been created with a lower jobId.
*/ private def getParentStages(rdd: RDD[_], jobId: Int): List[Stage] = {
val parents = new HashSet[Stage]
val visited = new HashSet[RDD[_]]
// We are manually maintaining a stack here to prevent StackOverflowError
// caused by recursively visiting
val waitingForVisit = new Stack[RDD[_]]
def visit(r: RDD[_]) {
if (!visited(r)) {
visited += r
// Kind of ugly: need to register RDDs with the cache here since
// we can't do it in its constructor because # of partitions is unknown
for (dep <- r.dependencies) {
dep match {
case shufDep: ShuffleDependency[_, _, _] =>
parents += getShuffleMapStage(shufDep, jobId)
case _ =>
waitingForVisit.push(dep.rdd)
}
}
}
} waitingForVisit.push(rdd)
while (!waitingForVisit.isEmpty) {
visit(waitingForVisit.pop())
}
parents.toList
}

上面这段代码看不懂,是用scala写的?

SparkContext拥有DAGScheduler的实例,在runJob方法中会进一步调用DAGScheduler的runJob方法。在此时,DAGScheduler会生成DAG和Stage,将Stage提交给TaskScheduler。TaskSchduler将Stage包装成TaskSet,发送到Worker节点进行真正的计算,同时还要监测任务状态,重试失败和长时间无返回的任务。整个过程如图所示:

2.3 RDD的缓存与容错

上文提到,Spark的计算是从action开始触发的,如果在action操作之前逻辑上很多transformation操作,一旦中间发生计算失败,Spark会重新提交任务,这在很多场景中代价过大。还有一些场景,如有些迭代算法,计算的中间结果会被重复使用,重复计算同样增加计算时间和造成资源浪费。因此,在提高计算效率和更好支持容错,Spark提供了基于RDDcache机制和checkpoint机制。

我们可以通过RDD的toDebugString来查看其递归的依赖信息,图6展示了在spark shell中通过调用这个函数来查看wordCount RDD的依赖关系,也就是它的Lineage.

如果发现Lineage过长或者里面有被多次重复使用的RDD,我们就可以考虑使用cache机制或checkpoint机制了。

我们可以通过在程序中直接调用RDD的cache方法将其保存在内存中,这样这个RDD就可以被多个任务共享,避免重复计算。另外,RDD还提供了更为灵活的persist方法,可以指定存储级别。从源码中可以看到RDD.cache就是简单的调用了RDD.persist(StorageLevel.MEMORY_ONLY)。

同样,我们可以调用RDD的checkpoint方法将其保存到磁盘。我们需要在SparkContext中设置checkpoint的目录,否则调用会抛出异常。值得注意的是,在调用checkpoint之前建议先调用cache方法将RDD放入内存,否则将RDD保存到文件的时候需要重新计算。

Cache机制和checkpoint机制的差别在于cache将RDD保存到内存,并保留Lineage,如果缓存失效RDD还可以通过Lineage重建。而checkpoint将RDD落地到磁盘并切断Lineage,由文件系统保证其重建。

2.4 Spark任务的部署

Spark的集群部署分为Standalone、Mesos和Yarn三种模式,我们以Standalone模式为例,简单介绍Spark程序的部署。

如图7示,集群中的Spark程序运行时分为3种角色,driver, master和worker(slave)。在集群启动前,首先要配置master和worker节点。启动集群后,worker节点会向master节点注册自己,master节点会维护worker节点的心跳。

Spark程序都需要先创建Spark上下文环境,也就是SparkContext。创建SparkContext的进程就成为了driver角色,上一节提到的DAGScheduler和TaskScheduler都在driver中运行。(在我之前的例子里面,bin/spark-submit 应该就是担任了driver的角色 )

Spark程序在提交时要指定master的地址,这样可以在程序启动时向master申请worker的计算资源。Driver,master和worker之间的通信由Akka支持。Akka 也使用 Scala 编写,用于构建可容错的、高可伸缩性的Actor 模型应用。关于Akka,可以访问其官方网站进行进一步了解,本文不做详细介绍。

 

3、更深一步了解Spark内核

了解了Spark内核的基本概念和实现后,更深一步理解其工作原理的最好方法就是阅读源码。最新的Spark源码可以从Spark官方网站下载

源码推荐使用IntelliJ IDEA阅读,会自动安装Scala插件。读者可以从core工程,也就是Spark内核工程开始阅读,更可以设置断点尝试跟踪一个任务的执行。

另外,读者还可以通过分析Spark的日志来进一步理解Spark的运行机制,Spark使用log4j记录日志,可以在启动集群前修改log4j的配置文件来配置日志输出和格式。

看完了上面对Spark的基本介绍后。实际应用参考了这个系列的文章:

http://www.cnblogs.com/shishanyuan/p/4699644.html

倾情大奉送--Spark入门实战系列

里面还有所使用数据的下载地址:http://pan.baidu.com/s/1o7HpDEy 密码:9xjt (网盘数据已经拷到我自己的网盘,目录 spark)

新开一些文章吧,免得文章太长了。

【转载】Spark学习——入门的更多相关文章

  1. Spark学习入门(让人看了想吐的话题)

    这是个老生常谈的话题,大家是不是看到这个文章标题就快吐了,本来想着手写一些有技术深度的东西,但是看到太多童鞋卡在入门的门槛上,所以还是打算总结一下入门经验.这种标题真的真的在哪里都可以看得到,度娘一搜 ...

  2. Spark学习入门

    Spark 是一种“One Stack to rule them all”通用的大数据计算框架,期望使用一个技术栈就完美地 解决大数据领域的各种计算任务. Spark特点:速度快.容易上手开发.超强的 ...

  3. [转载] redis学习入门 Redis 3.2.100

    参考博客: https://blog.csdn.net/flyer_tang/article/details/80320974 https://blog.csdn.net/weixin_3077313 ...

  4. spark学习笔记总结-spark入门资料精化

    Spark学习笔记 Spark简介 spark 可以很容易和yarn结合,直接调用HDFS.Hbase上面的数据,和hadoop结合.配置很容易. spark发展迅猛,框架比hadoop更加灵活实用. ...

  5. 大数据学习day18----第三阶段spark01--------0.前言(分布式运算框架的核心思想,MR与Spark的比较,spark可以怎么运行,spark提交到spark集群的方式)1. spark(standalone模式)的安装 2. Spark各个角色的功能 3.SparkShell的使用,spark编程入门(wordcount案例)

    0.前言 0.1  分布式运算框架的核心思想(此处以MR运行在yarn上为例)  提交job时,resourcemanager(图中写成了master)会根据数据的量以及工作的复杂度,解析工作量,从而 ...

  6. Spark快速入门 - Spark 1.6.0

    Spark快速入门 - Spark 1.6.0 转载请注明出处:http://www.cnblogs.com/BYRans/ 快速入门(Quick Start) 本文简单介绍了Spark的使用方式.首 ...

  7. Spark高速入门指南(Quick Start Spark)

    版权声明:本博客已经不再更新.请移步到Hadoop技术博客:https://www.iteblog.com https://blog.csdn.net/w397090770/article/detai ...

  8. [转] Spark快速入门指南 – Spark安装与基础使用

    [From] https://blog.csdn.net/w405722907/article/details/77943331 Spark快速入门指南 – Spark安装与基础使用 2017年09月 ...

  9. spark学习及环境配置

    http://dblab.xmu.edu.cn/blog/spark/ 厦大数据库实验室博客 总结.分享.收获 实验室主页 首页 大数据 数据库 数据挖掘 其他 子雨大数据之Spark入门教程  林子 ...

随机推荐

  1. acmer之ubuntu下安装Eclipse

    ubuntu是acmer常用的系统,配置起CB还是比较简单的三行命令就OK了 //Current stable version of Code::Blocks IDE (16.01) //To ins ...

  2. [转]zsh快捷键记录

    转自: http://wdxtub.com/2016/02/18/oh-my-zsh/ 使用技巧 连按两次Tab会列出所有的补全列表并直接开始选择,补全项可以使用 ctrl+n/p/f/b上下左右切换 ...

  3. java EE技术体系——CLF平台API开发注意事项(1)——后端开发

    前言:这是一篇帮助小伙伴在本次项目中快速进入到java EE开发的一些说明,为了让同组小伙伴们开发的时候,有个清晰点的思路.昨天给大家演示分享了基本概况,但没有留下文字总结说明,预防后期有人再次问我, ...

  4. pat 1037

    如果你是哈利·波特迷,你会知道魔法世界有它自己的货币系统 —— 就如海格告诉哈利的:“十七个银西可(Sickle)兑一个加隆(Galleon),二十九个纳特(Knut)兑一个西可,很容易.”现在,给定 ...

  5. 九度oj 题目1416:猴子吃坚果

    题目描述: 动物园的猴子吃坚果的顺序都是按强壮程度来定的,最强壮的吃完才能轮到下一个,现在我们给出各个猴子的名字,强壮程度,吃饱的量,然后查询对应的猴子必须要扔多少坚果才可以轮到. 输入: 输入有多组 ...

  6. Codeforces 903E Swapping Characters

    题目大意 考虑一个未知的长为 $n$($2\le n\le 5000$)由小写英文字母构成的字符串 $s$ .给出 $k$($1\le k\le 2500$,$nk\le 5000$)个字符串 $s_ ...

  7. HDU——2723Electronic Document Security(STL map嵌套set做法)

    Electronic Document Security Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K ( ...

  8. MongoDb C# 驱动操作示例

    c#操作mongo数据库 驱动采用http://www.oschina.net/p/mongo-csharp-driver C#驱动的基本数据库连接,增删改查操作 //定义对象 public clas ...

  9. Linq技巧4——怎么在.NET 3.5 SP1中伪造一个外键属性

    在.NET 4.0 的EF 中,增加了FK Associations 的功能,但是在.NET 3.5 SP1 中,仅仅支持独立的关联,这意味着FK 栏位不能作为实体的属性来使用,也就是说在使用的时候, ...

  10. 【CF721C】Journey(拓扑排序,最短路,DP)

    题意:给一个无环的图,问用不超过T的时间从1到n最多可以经过多少个点.要求输出一条路径. 思路:因为无环,可以用DP做.不过因为时间最短的原因要拓扑排序后再DP,目测由底向上的更新也是可以的. ; . ...