运行的时候
对spark内核进行解析,结合源码,能写基本代码
对 transformation 了解,map(),能写代码
Apache Spark is an open source cluster computing system that aims to make data analytics fast — both fast to run and fast to write
不仅分析快,写代码也快
以下为 the Berkeley Data Analytics Stack (BDAS)
Mesos 与 yarn 功效类似,有效区别
国内用 yarn 比较多,生态系统 yarn 更多一些
Mesos 的上一层是 分布式文件系统 HDFS
Tachyan 是分布式内存文件系统,并不仅支持 spark,也支持map-reduce
hadoop2.3.0 的datanode 也支持 cache(重大改进)
Spark Streaming Stream processing 是实时流处理
GraphX 是个图处理
MLlib 是个机器学习库
Shark SQL API 相当于 Hive on Spark ,相当于在 spark 上面建立一个 SQL
BlinkDB是海量数据上运行交互式SQL查询的大规模并行查询引擎,它允许用户通过传衡数据精度提升查询响应时间,可以将查询时间限制在误差范围之内
只需要一个站,就可以将所有都搞定了!无论是实时查询、流处理还是批处理,都可以实现
而以往的 Hadoop MapReduce来进行海量数据的分析,用 Strom 来进行实时流处理,Hive来做 SQL 处理,但维护这么多系统,必然会出现很多问题!spark 却不会出现这些问题,因为兼容好,原始设计的初衷也是这样。spark 是最有希望成为下一代分布式计算系统
面试必问题
Hadoop的数据共享?慢
为什么慢???额外的复制,序列化和磁盘IO开销
每次迭代操作写入和写出都是在 hdfs 上完成的。然而数据挖掘和机器学习 迭代次数非常多
将来 spark 从 datanode(有 cache)上取数据将非常完美了
十几G和百来G很适合 spark
很多优化措施其实是相通的,譬如说delay scheduling
比如 A节点上正在运行程序,当 B 节点需要从 A 节点上获取资源时,那么将延迟一段时间在执行。这样可以避免以往从忙碌的A节点上复制数据,这样是很耗费时间的,因为如果等待也许只需要几秒钟呢…
有4种模式可以运⾏
A function for computing each split
定义一个函数计算或迭代
A list of dependencies on other RDDs
一系列的依赖,RDD(a)->RDD(b)->RDD(c) ,则C 依赖 B ,B依赖A,这样就相互依赖
Optionally, a Partitioner for key-value RDDs (e.g. to say that the RDD is hash-partitioned)
告诉它怎么去分片的,利用小的技巧,可以避免很大的shuffle,避免宽依赖,优化成窄依赖
Optionally, a list of preferred locations to compute each split on(e.g. block locations for an HDFS file)
选择最优的计算机子来进行,
用户的 driver 程序,各个 worker 从分布式系统中获取数据并计算,把结果持久化。
其中的 transformation 操作是针对 RDD 操作的,且是延迟执行的(比如 map()操作),spark 并不会真正执行,而是会在原数据下记录下即将对 A 进行 map 操作。到 action 才会执行。
RDD可以从集合直接转换⽽而来,也可以由从现存的任何Hadoop InputFormat⽽而来,亦或者HBase等等,但国内应用比较少
class StorageLevel private(!
private var useDisk_ : Boolean,!
private var useMemory_ : Boolean,!
private var deserialized_ : Boolean,!
private var replication_ : Int = 1)!
val NONE = new StorageLevel(false, false, false)!
val DISK_ONLY = new StorageLevel(true, false, false)!
val DISK_ONLY_2 = new StorageLevel(true, false, false, 2)!
val MEMORY_ONLY = new StorageLevel(false, true, true)!
val MEMORY_ONLY_2 = new StorageLevel(false, true, true, 2)!
val MEMORY_ONLY_SER = new StorageLevel(false, true, false)!
val MEMORY_ONLY_SER_2 = new StorageLevel(false, true, false, 2)!
val MEMORY_AND_DISK = new StorageLevel(true, true, true)!
val MEMORY_AND_DISK_2 = new StorageLevel(true, true, true, 2)!
val MEMORY_AND_DISK_SER = new StorageLevel(true, true, false)!
val MEMORY_AND_DISK_SER_2 = new StorageLevel(true, true, false, 2)
其中 cache默认
val MEMORY_ONLY = new StorageLevel(false, true, true)!
transformation & action
Action:
进入 spark下的 bin 目录,启动 spark-shell
cd /home/hadoop/software/spark-1.0.2-bin-hadoop2/bin
./spark-shell
1. 分别执行以下命令(新手)
val rdd = sc.parallelize(List(1,2,34,5,6))
val mapRdd = rdd.map(2 * _)
mapRdd.collect
val filterRdd = mapRdd.filter(_ > 5)
filterRdd.collect
2. 一步到位(老手)
val filterRdd = sc.parallelize(List(1,2,34,5,6)).map(2 * _).filter(_ > 5).collect
vim ~/inputWord
内容如下:
hadoop fs -put ~/inputWord /data/wordcount/
hadoop fs -ls /data/wordcount
hadoop fs -text /data/wordcount/inputWord
进入 spark 的 sbin 目录下
cd /home/hadoop/software/spark-1.0.2-bin-hadoop2/sbin
./start-master.sh
显示如下:
starting org.apache.spark.deploy.master.Master, logging to /home/hadoop/software/spark-1.0.2-bin-hadoop2/sbin/../logs/spark-hadoop-org.apache.spark.deploy.master.Master-1-master.out
查看相应的 log 文件
cat logs/spark-hadoop-org.apache.spark.deploy.master.Master-1-master.out
可以看到输出的几条重要的信息,spark端口 7077,ui端口8080等,并且当前node通过选举,确认自己为leader,这个时候,我们可以通过 http://localhost:8080/ 来查看到当前master的总体状态
val rdd = sc.textFile("/data/wordcount/")
rdd.cache
rdd.count
Note:暂时只会从 HDFS上取数据,而不会从本地上取数据。在 HDFS 上的路径应是文件的上一层路径,不应包含文件名!切记!
val wordcount = rdd.flatMap(_.split(' ')).map((_,1)).reduceByKey(_+_)
wordcount.collect
期间,我们可以通过UI看到job列表和状态:
http://localhost:4040/stages/
val rdd1 = sc.parallelize(List(('a',1),('a',2)))
val rdd2 = sc.parallelize(List(('b',1),('b',2)))
val result = rdd1 union rdd2
result.collect
val rdd1 = sc.parallelize(List(('a',1),('a',2),('b',3),('b',4)))
val rdd2 = sc.parallelize(List(('a',5),('a',6),('b',7),('b',8)))
rdd1 join rdd2
res12.collect
val rdd1 = sc.parallelize(List(('a',1),('a',2),('b',3),('b',4)))
rdd1.lookup('a')
val rdd = sc.textFile("/data/spark_wordcount")
val wordcount = rdd.flatMap(_.split(' ' )).map((_,1)).reduceByKey(_+_).map(x => (x._2,x._1)).sortByKey(false).map(x => (x._2,x._1)).saveAsTextFile("/spark_outcome/")
程序执行成功之后,在另外一个终端输入命令以查看最终的结果
hadoop fs -ls -R /spark_outcome
hadoop fs -text /spark_outcome/part-00000
hadoop fs -text /spark_outcome/part-00001
每个子RDD都依赖前一个 RDD,一般会在中间制作个拷贝,防止最后的时刻某个 RDD 挂了
val logs = sc.textFile(…).filter(_.contains(“spark”)).map(_.split(‘\t’)(1))
每个RDD都会记录⾃自⼰己依赖于哪个(哪些)RDD,万⼀一某个RDD的某些 partition挂了,可以通过其它RDD并⾏行计算迅速恢复出来
大的框称之为 RDD,而小的实心矩形为 partition
窄依赖:一个 partition 最多只能被子 RDD 的一个 partion 所使用
宽依赖:一个 partition 可以被子 RDD 的多个 partion 所使用
map,filter 会导致窄依赖,而 join 会导致宽依赖。co-partition 也可以被认为是窄依赖
在一个节点上把所有的 partition 全部搞定,宽依赖只有等所有的副partition全部传输到节点上以后才开始计算。在宽依赖中,如果某个节点失效了,那么将重新计算,计算代价相当的大
左边的 RDD 计算出的结果,会存在 map端所在的磁盘
spark-env.sh
export JAVA_HOME=
export SPARK_MASTER_IP=
export SPARK_WORKER_CORES= // 分配给spark的CPU数量
export SPARK_WORKER_INSTANCES= // 划分出来的实例,普通的一个就够了
export SPARK_WORKER_MEMORY= // 给 spark 分配的内存
export SPARK_MASTER_PORT= // 设置的端口
export SPARK_JAVA_OPTS="-verbose:gc -XX:-PrintGCDetails -XX:+PrintGCTimeStamps”
slaves
xx.xx.xx.2
xx.xx.xx.3
xx.xx.xx.4
xx.xx.xx.5
/sbin 是存放一些启动和关闭集群的一些脚本
/bin 是存放 spark 启动关闭的程序,例如 spark-shell
MASTER=local[4] ADD_JARS=code.jar ./spark-shell
其中 local [4] 表示的是 几个本地线程
如果只是简单的启动,后面没有跟任何参数,那么默认是以 standalone 的方式启动
MASTER=spark://host:port
指定executor内存:export SPARK_MEM=25g
这个指定的 application 能用多少内存(这个命名可能将来会被废除)
spark-shell intends to set MASTER automatically if we do not provide the option when we start the shell , but there’s a problem. The condition is “if [[ “x” != “x$SPARK_MASTER_IP” && “y” != “y $
SPARK_MASTER_PORT” ]];” we sure will set SPARK_MASTER_IP explicitly, the SPARK_MASTER_PORT option, however, we probably do not set just using spark default port 7077. So if we do not set PARK_MASTER_PORT, the condition will never be true. We should just use default port if users do not set port explicitly I think.
spark.master spark://server1:8888
spark.local.dir /data/tmp_spark_dir/ // shuffle 过程中的临时目录
spark.executor.memory 10g // 设置内存
http://spark.apache.org/docs/latest/configuration.html