1、Spark手册【编者按】时至今日,Spark已成为大数据领域最火的一个开源项目,具备高性能、易于使用等特性。然而作为一个年轻的开源项目,其使用上存在的挑战亦不可为不大,这里为大家分享SciSpike软件架构师Ashwini Kuntamukkala在Dzone上进行的Spark入门总结(虽然有些地方基于的是Spark 1.0版本,但仍然值得阅读)Apache Spark:An Engine for Large-Scale Data Processing,由OneAPM工程师翻译。本文聚焦Apache Spark入门,了解其在大数据领域的地位,覆盖Apache Spark的安装及应用程序的建立,
2、并解释一些常见的行为和操作。一、 为什么要使用Apache Spark时下,我们正处在一个“大数据”的时代,每时每刻,都有各种类型的数据被生产。而在此紫外,数据增幅的速度也在显著增加。从广义上看,这些数据包含交易数据、社交媒体内容(比如文本、图像和视频)以及传感器数据。那么,为什么要在这些内容上投入如此多精力,其原因无非就是从海量数据中提取洞见可以对生活和生产实践进行很好的指导。在几年前,只有少部分公司拥有足够的技术力量和资金去储存和挖掘大量数据,并对其挖掘从而获得洞见。然而,被雅虎2009年开源的Apache Hadoop对这一状况产生了颠覆性的冲击通过使用商用服务器组成的集群大幅度地降低了
3、海量数据处理的门槛。因此,许多行业(比如Health care、Infrastructure、Finance、Insurance、Telematics、Consumer、Retail、Marketing、E-commerce、Media、 Manufacturing和Entertainment)开始了Hadoop的征程,走上了海量数据提取价值的道路。着眼Hadoop,其主要提供了两个方面的功能: 通过水平扩展商用主机,HDFS提供了一个廉价的方式对海量数据进行容错存储。 MapReduce计算范例,提供了一个简单的编程模型来挖掘数据并获得洞见。下图展示了MapReduce的数据处理流程,其中一
4、个Map-Reduce step的输出将作为下一个典型Hadoop job的输入结果。在整个过程中,中间结果会借助磁盘传递,因此对比计算,大量的Map-Reduced作业都受限于IO。然而对于ETL、数据整合和清理这样的用例来说,IO约束并不会产生很大的影响,因为这些场景对数据处理时间往往不会有较高的需求。然而,在现实世界中,同样存在许多对延时要求较为苛刻的用例,比如:1. 对流数据进行处理来做近实时分析。举个例子,通过分析点击流数据做视频推荐,从而提高用户的参与度。在这个用例中,开发者必须在精度和延时之间做平衡。2. 在大型数据集上进行交互式分析,数据科学家可以在数据集上做ad-hoc查询。
5、毫无疑问,历经数年发展,Hadoop生态圈中的丰富工具已深受用户喜爱,然而这里仍然存在众多问题给使用带来了挑战:1.每个用例都需要多个不同的技术堆栈来支撑,在不同使用场景下,大量的解决方案往往捉襟见肘。2.在生产环境中机构往往需要精通数门技术。3.许多技术存在版本兼容性问题。4.无法在并行job中更快地共享数据。而通过Apache Spark,上述问题迎刃而解!Apache Spark是一个轻量级的内存集群计算平台,通过不同的组件来支撑批、流和交互式用例,如下图。二、 关于Apache SparkApache Spark是个开源和兼容Hadoop的集群计算平台。由加州大学伯克利分校的AMPLa
6、bs开发,作为Berkeley Data Analytics Stack(BDAS)的一部分,当下由大数据公司Databricks保驾护航,更是Apache旗下的顶级项目,下图显示了Apache Spark堆栈中的不同组件。Apache Spark的5大优势:1.更高的性能,因为数据被加载到集群主机的分布式内存中。数据可以被快速的转换迭代,并缓存用以后续的频繁访问需求。很多对Spark感兴趣的朋友可能也会听过这样一句话在数据全部加载到内存的情况下,Spark可以比Hadoop快100倍,在内存不够存放所有数据的情况下快Hadoop 10倍。2.通过建立在Java、Scala、Python、SQ
7、L(应对交互式查询)的标准API以方便各行各业使用,同时还含有大量开箱即用的机器学习库。3.与现有Hadoop v1 (SIMR) 和2.x (YARN) 生态兼容,因此机构可以进行无缝迁移。4.方便下载和安装。方便的shell(REPL: Read-Eval-Print-Loop)可以对API进行交互式的学习。5.借助高等级的架构提高生产力,从而可以讲精力放到计算上。同时,Apache Spark由Scala实现,代码非常简洁。三、安装Apache Spark下表列出了一些重要链接和先决条件:Current Release1.0.1 Downloads Pagehttps:/spark.ap
8、ache.org/downloads.htmlJDK Version (Required)1.6 or higherScala Version (Required)2.10 or higherPython (Optional)2.6, 3.0)Simple Build Tool (Required)http:/www.scala-sbt.orgDevelopment Versiongit clone git:/Building Instructionshttps:/spark.apache.org/docs/latest/building-with-maven.htmlMaven3.0 or
9、higher如图6所示,Apache Spark的部署方式包括standalone、Hadoop V1 SIMR、Hadoop 2 YARN/Mesos。Apache Spark需求一定的Java、Scala或Python知识。这里,我们将专注standalone配置下的安装和运行。1.安装JDK 1.6+、Scala 2.10+、Python 2.6,3 和sbt2.下载Apache Spark 1.0.1 Release3.在指定目录下Untar和Unzip spark-1.0.1.tgzakuntamukkalalocalhost/Downloads$ pwd /Users/akunta
10、mukkala/Downloads akuntamukkalalocalhost/Downloads$ tar -zxvf spark- 1.0.1.tgz -C /Users/akuntamukkala/spark4.运行sbt建立Apache Sparkakuntamukkalalocalhost/spark/spark-1.0.1$ pwd /Users/akuntamukkala/spark/spark-1.0.1 akuntamukkalalocalhost/spark/spark-1.0.1$ sbt/sbt assembly5.发布Scala的Apache Spark stand
11、alone REPL/Users/akuntamukkala/spark/spark-1.0.1/bin/spark-shell如果是Python/Users/akuntamukkala/spark/spark-1.0.1/bin/ pyspark6.查看SparkUI http:/localhost:4040四、Apache Spark的工作模式Spark引擎提供了在集群中所有主机上进行分布式内存数据处理的能力,下图显示了一个典型Spark job的处理流程。下图显示了Apache Spark如何在集群中执行一个作业。Master控制数据如何被分割,利用了数据本地性,并在Slaves上跟踪所
12、有分布式计算。在某个Slave不可用时,其存储的数据会分配给其他可用的Slaves。虽然当下(1.0.1版本)Master还存在单点故障,但后期必然会被修复。五、弹性分布式数据集(Resilient Distributed Dataset,RDD)弹性分布式数据集(RDD,从Spark 1.3版本开始已被DataFrame替代)是Apache Spark的核心理念。它是由数据组成的不可变分布式集合,其主要进行两个操作:transformation和action。Transformation是类似在RDD上做 filter()、map()或union() 以生成另一个RDD的操作,而action
13、则是count()、first()、take(n)、collect() 等促发一个计算并返回值到Master或者稳定存储系统的操作。Transformations一般都是lazy的,直到action执行后才会被执行。Spark Master/Driver会保存RDD上的Transformations。这样一来,如果某个RDD丢失(也就是salves宕掉),它可以快速和便捷地转换到集群中存活的主机上。这也就是RDD的弹性所在。下图展示了Transformation的lazy:我们可以通过下面示例来理解这个概念:从文本中发现5个最常用的word。下图显示了一个可能的解决方案。在上面命令中,我们对文
14、本进行读取并且建立字符串的RDD。每个条目代表了文本中的1行。scala val hamlet = sc.textFile(“/Users/akuntamukkala/temp/gutenburg.txt”)hamlet: org.apache.spark.rdd.RDDString = MappedRDD1 at textFile at :12scala val topWordCount = hamlet.flatMap(str=str.split(“ “). filter(!_.isEmpty).map(word=(word,1).reduceByKey(_+_).mapcase (wor
15、d, count) = (count, word).sortByKey(false)topWordCount: org.apache.spark.rdd.RDD(Int, String) = MapPartitionsRDD10 at sortByKey at :141.通过上述命令我们可以发现这个操作非常简单通过简单的Scala API来连接transformations和actions。2.可能存在某些words被1个以上空格分隔的情况,导致有些words是空字符串,因此需要使用filter(!_.isEmpty)将它们过滤掉。3.每个word都被映射成一个键值对:map(word=(wo
16、rd,1)。4.为了合计所有计数,这里需要调用一个reduce步骤reduceByKey(_+_)。 _+_ 可以非常便捷地为每个key赋值。5.我们得到了words以及各自的counts,下一步需要做的是根据counts排序。在Apache Spark,用户只能根据key排序,而不是值。因此,这里需要使用mapcase (word, count) = (count, word)将(word, count)流转到(count, word)。6.需要计算最常用的5个words,因此需要使用sortByKey(false)做一个计数的递减排序。上述命令包含了一个.take(5) (an actio
17、n operation, which triggers computation)和在 /Users/akuntamukkala/temp/gutenburg.txt文本中输出10个最常用的words。在Python shell中用户可以实现同样的功能。RDD lineage可以通过toDebugString(一个值得记住的操作)来跟踪。scala topWordCount.take(5).foreach(x=println(x)(1044,the)(730,and)(679,of)(648,to)(511,I)常用的Transformations:Transformation & Purpos
18、eExample & Resultfilter(func)Purpose:new RDD by selecting those data elements on which func returns truescala val rdd = sc.parallelize(List(“ABC”,”BCD”,”DEF”) scala val filtered = rdd.filter(_.contains(“C”) scala filtered.collect()Result:ArrayString = Array(ABC, BCD)map(func)Purpose:return new RDD b
19、y applying func on each data elementscala val rdd=sc.parallelize(List(1,2,3,4,5) scala val times2 = rdd.map(_*2) scala times2.collect()Result:ArrayInt = Array(2, 4, 6, 8, 10)flatMap(func)Purpose:Similar to map but func returns a Seq instead of a value. For example, mapping a sentence into a Seq of w
20、ordsscala val rdd=sc.parallelize(List(“Spark is awesome”,”It is fun”) scala val fm=rdd.flatMap(str=str.split(“ “) scala fm.collect()Result:ArrayString = Array(Spark, is, awesome, It, is, fun)reduceByKey(func,numTasks)Purpose:To aggregate values of a key using a function. “numTasks” is an optional pa
21、rameter to specify number of reduce tasksscala val word1=fm.map(word=(word,1) scala val wrdCnt=word1.reduceByKey(_+_) scala wrdCnt.collect()Result:Array(String, Int) = Array(is,2), (It,1), (awesome,1), (Spark,1), (fun,1)groupByKey(numTasks)Purpose:To convert (K,V) to (K,Iterable)scala val cntWrd = w
22、rdCnt.mapcase (word, count) = (count, word) scala cntWrd.groupByKey().collect()Result:Array(Int, IterableString) = Array(1,ArrayBuffer(It, awesome, Spark, fun), (2,ArrayBuffer(is)distinct(numTasks)Purpose:Eliminate duplicates from RDDscala fm.distinct().collect()Result:ArrayString = Array(is, It, aw
23、esome, Spark, fun)常用的集合操作:Transformation and PurposeExample and Resultunion()Purpose:new RDD containing all elements from source RDD and argument.Scala val rdd1=sc.parallelize(List(A,B)scala val rdd2=sc.parallelize(List(B,C)scala rdd1.union(rdd2).collect()Result:ArrayChar = Array(A, B, B, C)intersec
24、tion()Purpose:new RDD containing only common elements from source RDD and argument.Scala rdd1.intersection(rdd2).collect()Result:ArrayChar = Array(B)cartesian()Purpose:new RDD cross product of all elements from source RDD and argumentScala rdd1.cartesian(rdd2).collect()Result:Array(Char, Char) = Arr
25、ay(A,B), (A,C), (B,B), (B,C)subtract()Purpose:new RDD created by removing data elements in source RDD in common with argumentscala rdd1.subtract(rdd2).collect()Result:ArrayChar = Array(A)join(RDD,numTasks)Purpose:When invoked on (K,V) and (K,W), this operation creates a new RDD of (K, (V,W)scala val
26、 personFruit = sc.parallelize(Seq(“Andy”, “Apple”), (“Bob”, “Banana”), (“Charlie”, “Cherry”), (“Andy”,”Apricot”)scala val personSE = sc.parallelize(Seq(“Andy”, “Google”), (“Bob”, “Bing”), (“Charlie”, “Yahoo”), (“Bob”,”AltaVista”)scala personFruit.join(personSE).collect()Result:Array(String, (String,
27、 String) = Array(Andy,(Apple,Google), (Andy,(Apricot,Google), (Charlie,(Cherry,Yahoo), (Bob,(Banana,Bing), (Bob,(Banana,AltaVista)cogroup(RDD,numTasks)Purpose:To convert (K,V) to (K,Iterable)scala personFruit.cogroup(personSe).collect()Result:Array(String, (IterableString, IterableString) = Array(An
28、dy,(ArrayBuffer(Apple, Apricot),ArrayBuffer(google), (Charlie,(ArrayBuffer(Cherry),ArrayBuffer(Yahoo), (Bob,(ArrayBuffer(Banana),ArrayBuffer(Bing, AltaVista)更多transformations信息,请查看http:/spark.apache.org/docs/latest/programming-guide.html#transformations常用的actionsAction & PurposeExample & Resultcount
29、()Purpose:get the number of data elements in the RDDscala val rdd = sc.parallelize(list(A,B,c) scala rdd.count()Result:long = 3collect()Purpose:get all the data elements in an RDD as an arrayscala val rdd = sc.parallelize(list(A,B,c) scala rdd.collect()Result:Arraychar = Array(A, B, c)reduce(func)Pu
30、rpose:Aggregate the data elements in an RDD using this function which takes two arguments and returns onescala val rdd = sc.parallelize(list(1,2,3,4) scala rdd.reduce(_+_)Result:Int = 10take (n)Purpose: fetch first n data elements in an RDD. computed by driver program.Scala val rdd = sc.parallelize(list(1,2,3,4) scala rdd.take(2)Result:ArrayInt = Array(1, 2)foreach(func)Purpose:execute function for each data element in RDD. usually used to update an accumulator(discussed later) or interacting with external systems.Scala val rd
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1