这样你可以简单地下载新/旧版本的Spark,然后修改链接来管理Spark版本,而不用更改路径或环境变量。
1
~$ln-s/srv/spark-1.2.0/srv/spark
4.修改BASH配置,将Spark添加到PATH中,设置SPARK_HOME环境变量。
这些小技巧在命令行上会帮到你。
在Ubuntu上,只要编辑~/.bash_profile或~/.profile文件,将以下语句添加到文件中:
1
2
exportSPARK_HOME=/srv/spark
exportPATH=$SPARK_HOME/bin:
$PATH
5.source这些配置(或者重启终端)之后,你就可以在本地运行一个pyspark解释器。
执行pyspark命令,你会看到以下结果:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
~$pyspark
Python2.7.8(default,Dec 22014,12:
45:
58)
[GCC4.2.1CompatibleAppleLLVM6.0(clang-600.0.54)]ondarwin
Type"help","copyright","credits"or"license"formoreinformation.
SparkassemblyhasbeenbuiltwithHive,includingDatanucleusjarsonclasspath
UsingSparksdefaultlog4jprofile:
org/apache/spark/log4j-defaults.properties
[…snip…]
Welcometo
____ __
/__/__ ________//__
_\\/_\/_`/__/ `_/
/__/.__/\_,_/_//_/\_\ version1.2.0
/_/
UsingPythonversion2.7.8(default,Dec 2201412:
45:
58)
SparkContextavailableassc.
>>>
现在Spark已经安装完毕,可以在本机以”单机模式“(standalonemode)使用。
你可以在本机开发应用并提交Spark作业,这些作业将以多进程/多线程模式运行的,或者,配置该机器作为一个集群的客户端(不推荐这样做,因为在Spark作业中,驱动程序(driver)是个很重要的角色,并且应该与集群的其他部分处于相同网络)。
可能除了开发,你在本机使用Spark做得最多的就是利用spark-ec2脚本来配置Amazon云上的一个EC2Spark集群了。
简略Spark输出
Spark(和PySpark)的执行可以特别详细,很多INFO日志消息都会打印到屏幕。
开发过程中,这些非常恼人,因为可能丢失Python栈跟踪或者print的输出。
为了减少Spark输出–你可以设置$SPARK_HOME/conf下的log4j。
首先,拷贝一份$SPARK_HOME/conf/log4j.properties.template文件,去掉“.template”扩展名。
1
~$cp$SPARK_HOME/conf/log4j.properties.template$SPARK_HOME/conf/log4j.properties
编辑新文件,用WARN替换代码中出现的INFO。
你的log4j.properties文件类似:
1
2
3
4
5
6
7
8
9
10
11
#Seteverythingtobeloggedtotheconsole
log4j.rootCategory=WARN,console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.target=System.err
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yy/MM/ddHH:
mm:
ss}%p%c{1}:
%m%n
#Settingstoquietthirdpartylogsthataretooverbose
log4j.logger.org.eclipse.jetty=WARN
ponent.AbstractLifeCycle=ERROR
log4j.logger.org.apache.spark.repl.SparkIMain$exprTyper=WARN
log4j.logger.org.apache.spark.repl.SparkILoop$SparkILoopInterpreter=WARN
现在运行PySpark,输出消息将会更简略!
感谢@genomegeek在一次DistrictDataLabs的研讨会中指出这一点。
在Spark中使用IPythonNotebook
当搜索有用的Spark小技巧时,我发现了一些文章提到在PySpark中配置IPythonnotebook。
IPythonnotebook对数据科学家来说是个交互地呈现科学和理论工作的必备工具,它集成了文本和Python代码。
对很多数据科学家,IPythonnotebook是他们的Python入门,并且使用非常广泛,所以我想值得在本文中提及。
这里的大部分说明都来改编自IPythonnotebook:
在PySpark中设置IPython。
但是,我们将聚焦在本机以单机模式将IPtyonshell连接到PySpark,而不是在EC2集群。
如果你想在一个集群上使用PySpark/IPython,查看并评论下文的说明吧!
1.1.为Spark创建一个iPythonnotebook配置
1
2
3
4
~$ipythonprofilecreatespark
[ProfileCreate]Generatingdefaultconfigfile:
u'$HOME/.ipython/profile_spark/ipython_config.py'
[ProfileCreate]Generatingdefaultconfigfile:
u'$HOME/.ipython/profile_spark/ipython_notebook_config.py'
[ProfileCreate]Generatingdefaultconfigfile:
u'$HOME/.ipython/profile_spark/ipython_nbconvert_config.py'
记住配置文件的位置,替换下文各步骤相应的路径:
2.创建文件$HOME/.ipython/profile_spark/startup/00-pyspark-setup.py,并添加如下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
importos
importsys
#Configuretheenvironment
if'SPARK_HOME'notinos.environ:
os.environ['SPARK_HOME']='/srv/spark'
#Createavariableforourrootpath
SPARK_HOME=os.environ['SPARK_HOME']
#AddthePySpark/py4jtothePythonPath
sys.path.insert(0,os.path.join(SPARK_HOME,"python","build"))
sys.path.insert(0,os.path.join(SPARK_HOME,"python"))
3.使用我们刚刚创建的配置来启动IPythonnotebook。
1
~$ipythonnotebook--profilespark
4.在notebook中,你应该能看到我们刚刚创建的变量。
1
printSPARK_HOME
5.在IPythonnotebook最上面,确保你添加了Sparkcontext。
1
2
frompysparkimport SparkContext
sc=SparkContext('local','pyspark')
6.使用IPython做个简单的计算来测试Sparkcontext。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
defisprime(n):
"""
checkifintegernisaprime
"""
#makesurenisapositiveinteger
n=abs(int(n))
#0and1arenotprimes
ifn<2:
returnFalse
#2istheonlyevenprimenumber
ifn==2:
returnTrue
#allotherevennumbersarenotprimes
ifnotn&1:
returnFalse
#rangestartswith3andonlyneedstogoupthesquarerootofn
#foralloddnumbers
forxinrange(3,int(n**0.5)+1,2):
ifn%x==0:
returnFalse
returnTrue
#CreateanRDDofnumbersfrom0to1,000,000
nums=sc.parallelize(xrange(1000000))
#ComputethenumberofprimesintheRDD
printnums.filter(isprime).count()
如果你能得到一个数字而且没有错误发生,那么你的context正确工作了!
编辑提示:
上面配置了一个使用PySpark直接调用IPythonnotebook的IPythoncontext。
但是,你也可以使用PySpark按以下方式直接启动一个notebook:
$IPYTHON_OPTS=”notebook–pylabinline”pyspark
哪个方法好用取决于你使用PySpark和IPython的具体情景。
前一个允许你更容易地使用IPythonnotebook连接到一个集群,因此是我喜欢的方法。
在EC2上使用Spark
在讲授使用Hadoop进行分布式计算时,我发现很多可以通过在本地伪分布式节点(pseudo-distributednode)或以单节点模式(single-nodemode)讲授。
但是为了了解真正发生了什么,就需要一个集群。
当数据变得庞大,这些书面讲授的技能和真实计算需求间经常出现隔膜。
如果你肯在学习详细使用Spark上花钱,我建议你设置一个快速Spark集群做做实验。
包含5个slave(和1个master)每周大概使用10小时的集群每月大概需要$45.18。
完整的讨论可以在Spark文档中找到:
在EC2上运行Spark在你决定购买EC2集群前一定要通读这篇文档!
我列出了一些关键点:
1.通过AWSConsole获取AWSEC2key对(访问key和密钥key)。
2.将key对导出到你的环境中。
在shell中敲出以下命令,或者将它们添加到配置中。
1
2
exportAWS_ACCESS_KEY_ID=myaccesskeyid
exportAWS_SECRET_ACCESS_KEY=mysecretaccesskey
注意不同的工具使用不同的环境名称,确保你用的是Spark脚本所使用的名称。
3.启动集群:
1
2
~$cd$SPARK_HOME/ec2
ec2$./spark-ec2-k-i-slaunch
4.SSH到集群来运行Spark作业。
1
ec2$./spark-ec2-k-ilogin
5.销毁集群
1
ec2$./spark-ec2destroy<cluster-name>.
这些脚本会自动创建一个本地的HDFS集群来添加数据,copy-dir命令可以同步代码和数据到该集群。
但是你最好使用S3来存储数据,创建使用s3:
//URI来加载数据的RDDs。
Spark是什么?
既然设置好了Spark,现在我们讨论下Spark是什么。
Spark是个通用的集群计算框架,通过将大量数据集计算任务分配到多台计算机上,提供高效内存计算。
如果你熟悉Hadoop,那么你知道分布式计算框架要解决两个问题:
如何分发数据和如何分发计算。
Hadoop使用HDFS来解决分布式数据问题,MapReduce计算范式提供有效的分布式计算。
类似的,Spark拥有多种语言的函数式编程API,提供了除map和reduce之外更多的运算符,这些操作是通过一个称作弹性分布式数据集(resilientdistributeddatasets,RDDs)的分布式数据框架进行的。
本质上,RDD是种编程抽象,代表可以跨机器进行分割的只读对象集合。
RDD可以从一个继承结构(lineage)重建(因此可以容错),通过并行操作访问,可以读写HDFS或S3这样的分布式存储,更重要的是,可以缓存到worker节点的内存中进行立即重用。
由于RDD可以被缓存在内存中,Spark对迭代应用特别有效,因为这些应用中,数据是在整个算法运算过程中都可以被重用。
大多数机器学习和最优化算法都是迭代的,使得Spark对数据科学来说是个非常有效的工具。
另外,由于Spark非常快,可以通过类似PythonREPL的命令行提示符交互式访问。
Spark库本身包含很多应用元素,这些元素可以用到大部分大数据应用中,其中包括对大数据进行类似SQL查询的支持,机器学习和图算法,甚至对实时流数据的支持。
核心组件如下:
∙SparkCore:
包含Spark的基本功能;尤其是定义RDD的API、操作以及这两者上的动作。
其他Spark的库都是构建在RDD和SparkCore之上的。
∙SparkSQL:
提供通过ApacheHive的SQL变体Hive查询语言(HiveQL)与Spark进行交互的API。
每个数据库表被当做一个RDD,SparkSQL查询被转换为Spark操作。
对熟悉Hive和HiveQL的人,Spark可以拿来就用。
∙SparkStreaming:
允许对实时数据流进行处理和控制。
很多实时数据库(如ApacheStore)可以处理实时数据。
SparkStreaming允许程序能够像普通RDD一样处理实时数据。
∙MLlib:
一个常用机器学习算法库,算法被实现为对RDD的Spark操作。
这个库包含可扩展的学习算法,比如分类、回归等需要对大量数据集进行迭代的操作。
之前可选的大数据机器学习库Mahout,将会转到Spark,并在未来实现。
∙GraphX:
控制图、并行图操作和计算的一组算法和工具的集合。
GraphX扩展了RDDAPI,包含控制图、创建子图、访问路径上所有顶点的操作。
由于这些组件满足了很多大数据需求,也满足了很多数据科学任务的算法和计算上的需要,Spark快速流行起来。
不仅如此,Spark也提供了使用Scala、Java和Python编写的API;满足了不同团体的需求,允许更多数据科学家简便地采用Spark作为他们的大数据解决方案。
对Spark编程
编写Spark应用与之前实现在Hadoop上的其他数据流语言类似。
代码写入一个惰性求值的驱动程序(driverprogram)中,通过一个动作(action),驱动代码被分发到集群上,由各个RDD分区上的worker来执行。
然后结果会被发送回驱动程序进行聚合或编译。
本质上,驱动程序创建一个或多个RDD,调用操作来转换RDD,然后调用动作处理被转换后的RDD。
这些步骤大体如下:
1.定义一个或多个RDD,可以通过获取存储在磁盘上的数据(HDFS,Cassandra,HBase,LocalDisk),并行化内存中的某些集合,转换(transform)一个已存在的RDD,或者,缓存或保存。
2.通过传递一个闭包(函数)给RDD上的每个元素来调用RDD上的操作。
Spark提供了除了Map和Reduce的80多种高级操作。
3.使用结果RDD的动作(action)(如count、collect、save等)。
动作将会启动集群上的计算。
当Spark在一个worker上运行闭包时,闭包中用到的所有变量都会被拷贝到节点上,但是由闭包的局部作用域来维护。
Spark提供了两种类型的共享变量,这些变量可以按照限定的方式被所有worker访问。
广播变量会被分发给所有worker,但是是只读的。
累加器这种变量,worker可以使用关联操作来“加”,通常用作计数器。
Spark应用本质上通过转换和动作来控制RDD。
后续文章将会深入讨论,但是理解了这个就足以执行下面的例子了。
Spark的执行
简略描述下Spark的执行。
本质上,Spark应用作为独立的进程运行,由驱动程序中的SparkContext协调。
这个context将会连接到一些集群管理者(如YARN),这些管理者分配系统资源。
集群上的每个worker由执行者(executor)管理,执行者反过来由SparkContext管理。
执行者管理计算、存储,还有每台机器上的缓存。
重点要记住的是应用代码由驱动程序发送给执行者,执行者指定context和要运行的任务。
执行者与驱动程序通信进行数据分享或者交互。
驱动程序是Spark作业的主要参与者,因此需要与集群处于相同的网络。
这与Hadoop代码不同,Hadoop中你可以在任意位置提交作业给JobTracker,JobTracker处理集群上的执行。
与Spark交互
使用Spark最简单的方式就是使用交互式命令行提示符。
打开PySpark终端,在命令行中打出pyspark。
1
2
3
~$