Spark介绍
Spark是UC Berkeley AMP lab (加州大学伯克利分校的AMP实验室)所开源的,后贡献给Apache。是一种快速、通用、可扩展的大数据分析引
擎。它是不断壮大的大数据分析解决方案家族中备受关注的明星成员,为分布式数据集的处理提供了一个有效框架,并以高效的方式处理分布式数据集。Spark集批处理、实时流处理、交互式查询、机器学习与图计算于一体,避免了多种运算场景下需要部署不同集群带来的资源浪费。目前, Spark社区也成为大数据领域和Apache软件基金会最活跃的项目之一, 其活跃度甚至远超曾经只能望其项背的Hadoop。
Spark的技术背景
无论是工业界还是学术界,都已经广泛使用高级集群编程模型来处理日益增长的数据,如MapReduce和Dryad。这些系统将分布式编程简化为自动提供位置感知性调度、容错以及负载均衡,使得大量用户能够在商用集群上分析超大数据集。
大多数现有的集群计算系统都是基于非循环的数据流模型。即从稳定的物理存储(如分布式文件系统)中加载记录,记录被传入由一组确定性操作
构成的DAG(Directed Acyclic Graph,有向无环图),然后写回稳定存储。DAG数据流图能够在运行时自动实现任务调度和故障恢复。
尽管非循环数据流是一种很强大的抽象方法,但仍然有些应用无法使用这种方式描述。这类应用包括:①机器学习和图应用中常用的迭代算法(每一步对数据执行相似的函数)
②交互式数据挖掘工具(用户反复查询一个数据子集)
基于数据流的框架并不明确支持工作集,所以需要将数据输出到磁盘,然后在每次查询时重新加载,这会带来较大的开销。针对上述问题,Spark 实现了一种分布式的内存抽象,称为弹性分布式数据集
(Resilient Distributed Dataset,RDD )。它支持基于工作集的应用, 同时具有数据流模型的特点:自动容错、位置感知性调度和可伸缩
性。RDD允许用户在执行多个查询时显式地将工作集缓存在内存中,后续的查询能够重用工作集,这极大地提升了查询速度。
Spark单机模式安装
实现步骤:
1)安装和配置好JDK
2)上传和解压Spark安装包
3)进入Spark安装目录下的conf目录
复制conf spark-env.sh.template 文件为 spark-env.sh 在其中修改,增加如下内容:
SPARK_LOCAL_IP=服务器IP地址
Spark单机模式启动
在bin目录下执行:sh spark-shell --master=local
启动后 发现打印消息
Spark context Web UI available at http://192.168.242.101:4040//Spark的浏览器界面
Spark context available as ‘sc’ (master = local, app id = local-1490336686508).//Spark 提供了环境对象 sc
Spark session available as ‘spark’.//Spark提供了会话独享spark
Spark VS MapReduce
MapReduce存在的问题
一个 Hadoop job 通常都是这样的: 1)从 HDFS 读取输入数据;
2)在 Map 阶段使用用户定义的 mapper function, 然后把结果Spill到磁盘;
3)在 Reduce 阶段,从各个处于 Map 阶段的机器中读取 Map 计算的中间结果,使用用户定义的 reduce function, 通常最后把结果写回 HDFS;
Hadoop的问题在于,一个 Hadoop job 会进行多次磁盘读写,比如写入机器本地磁盘,或是写入分布式文件系统中(这个过程包含磁盘的读写以及网络传输)。考虑到磁盘读取比内存读取慢了几个数量级,所以像 Hadoop 这样高度依赖磁盘读写的架构就一定会有性能瓶颈。
此外,在实际应用中我们通常需要设计复杂算法处理海量数据, 而且不是一个 Hadoop job 可以完成的。比如机器学习领域,需要大量使用迭代的方法训练机器学习模型。而像 Hadoop 的基本模型就只包括了一个 Map 和 一个 Reduce 阶段,想要完成复杂运算就需要切分出无数单独的 Hadoop jobs, 而且每个 Hadoop job 都是磁盘读写大户,这就让 Hadoop 显得力不从心。
随着业界对大数据使用越来越深入,大家都呼唤一个更强大的处理框架,能够真正解决更多复杂的大数据问题。
Spark的优势
2009年,美国加州大学伯克利分校的 AMPLab 设计并开发了名叫 Spark 的大数据处理框架。真如其名,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 真的赶上了好时候,企业可以轻松部署多台大内存机器,内存大到可以装载所有要处理的数据。
RDD介绍
概述
Resilient Distributed Datasets (RDDs)
RDD就是带有分区的集合类型
弹性分布式数据集(RDD),特点是可以并行操作,并且是容错的。有两种方法可以创建RDD:
1)执行Transform操作(变换操作),
2)读取外部存储系统的数据集,如HDFS,HBase,或任何与Hadoop有关的数据源。
RDD入门示例
案例一:
Parallelized collections are created by
calling SparkContext’s parallelize method on an existing collection in your driver program (a Scala Seq). The elements of the collection are copied to form a distributed dataset that can be operated on in parallel. For example, here is how to create a parallelized collection holding the numbers 1 to 5:
你可以这样理解RDD:它是spark提供的一个特殊集合类。诸如普通的集 合类型,如传统的Array:(1,2,3,4,5)是一个整体,但转换成RDD后, 我们可以对数据进行Partition(分区)处理,这样做的目的就是为了分布式。
你可以让这个RDD有两个分区,那么有可能是这个形式:RDD(1,2) (3,4)。
这样设计的目的在于:可以进行分布式运算。
注:创建RDD的方式有多种,比如案例一中是基于一个基本的集合类型
(Array)转换而来,像parallelize这样的方法还有很多,之后就会学到。此外,我们也可以在读取数据集时就创建RDD。
案例二:
Spark can create distributed datasets from any storage source supported by Hadoop, including your local file system, HDFS, Cassandra, HBase, Amazon S3, etc. Spark supports text
files, SequenceFiles, and any other Hadoop InputFormat.
Text file RDDs can be created
using SparkContext’s textFile method. This method takes an URI for the file (either a local path on the machine, or
a hdfs://, s3n://, etc URI) and reads it as a collection of lines. Here is an example invocation:
val distFile = sc.textFile("data.txt")
查 看 RDD
scala>rdd.collect
收集rdd中的数据组成Array返回,此方法将会把分布式存储的rdd中的数据
集中到一台机器中组建Array。
在生产环境下一定要慎用这个方法,容易内存溢出。查看RDD的分区数量:scala>rdd.partitions.size
查看RDD每个分区的元素:scala>rdd.glom.collect 此方法会将每个分区的元素以Array形式返回
分区概念
在上图中, 一个RDD有item1~item25个数据,共5个分区,分别在3台机器上进行处理。
此外,spark并没有原生的提供rdd的分区查看工具 我们可以自己来写一个
示例代码:
import org.apache.spark.rdd.RDD import scala.reflect.ClassTag object su {
def debug[T: ClassTag](rdd: RDD[T]) = {
rdd.mapPartitionsWithIndex((i: Int, iter: Iterator[T]) => {
val m = scala.collection.mutable.Map[Int, List[T]]()
var list = List[T]() while (iter.hasNext) { list = list :+ iter.next
}
m(i) = list m.iterator
}).collect().foreach((x: Tuple2[Int, List[T]]) => { val i = x._1
println(s"partition:[$i]") x._2.foreach { println }
})
}
}
RDD操作
概述
针对RDD的操作,分两种,一种是Transformation(变换),一种是Actions(执行)。Transformation(变换)操作属于懒操作,不会真正触发RDD的处理计算。 Actions(执行)操作才会真正触发。
Actions
案例:通过rdd实现统计文件中的单词数量sc.textFile(“/root/work/words.txt”).flatMap(.split(" ")).map((,1)).reduceByKey(+).saveAsTextFile(“/root/work/wcresult”)